I work for a web development company in Edinburgh called Storm ID (http://www.stormid.com). We love staying at the forefront of web technology; ASP.NET MVC, WCF, Silverlight....
Our company's Silverlight guru is Bob Thomson. "The Drum" (http://www.thedrum.co.uk) has published an article on Bob's thought's on Silverlight 2.0:
"Hi Ho Silver! Has Flash Had Its Day?"
http://www.thedrum.co.uk/indepth/1650-hi-ho-silver-has-flash-had-its-day-
Love the title Bob!
Bob discuses all the current Web technologies from Flex/Flash, HTML/JavaScript/AJAX, to Silverlight and Microsoft Mesh. Really interesting article.
All we need now is a Bob to set up his own blog so the rest of us can keep up with his "cutting edge" Silverlight development. "Come on Bob....how about it!"
The likelihood of you not knowing what Google Chrome is very very slim.... but just in case here is the link: http://www.google.com/chrome/
Must Have's
As a web developer my default browser must be able to handle certain developer needs (other than rendering the website/application correctly).
The most useful web developer tool is a very well known guru of an add-on for Firefox:
You guessed it Firebug!
So my first question is "What does Chrome offer?"
Goggle Chrome has it's very own "Inspector":
This is nice Google! Clearly based of Firebug, Chromes version has all the stuff (sorry for being so technical!) you would expect.
The UI is very much like the rest of the browser: clean, simple and nice to use. Far better that IE8's version of the Developer Toolbar.
To bring up the inspector you can either right click on any element on your web page and select "Inspect element" or select "Developer" -> "JavaScript console " from the Page menu
.
What else?
There are loads of feature in Google Chrome...and lots of features to come, but as a web developer it renders fast, looks great, works well...and therefore I setting Google Chrome as my default browser...for now.
What do you think?
After a long battle I managed to update my 1.9.5 installation to SubText 2.0 on my shared hosting environment.
I had to install all the SQL scripts manually, and I also had to build the trunk version of SubText to get round the problem of Medium Trust on shared hosting servers.
While I was at it I decided that it was time to change the theme...with a few tweaks that should be it sorted.
Also while I was at it I thought I'd try out using Windows Live Writer to publish my posts, since SubText now supports it.
Well...here goes
As I'm sure you are all aware that the guys have released Preview 5 of
ASP.NET MVC Framework.
This preview has had a lot of changes since preview 4 and this means a lot of changes to get a preview 4 application building (and running correctly) against preview 5.
I have managed to get my application running (eventually!). Here are the main areas that I had to change to get it working:
New dlls
Almost goes with out saying but you need to reference the new set of dlls
- System.Web.Mvc
- System.Web.Abstractions
- System.Web.Routing
- Microsoft.Web.Mvc
Web.config change
System.Web.Abstractions and
System.Web.Routing are now at version 3.5.0.0; therefore you must update all references in the
web.config from
Version=0.0.0.0 to
Version=3.5.0.0
No More BindingHelperExtensions.UpdateFrom() Method
Preview 5 now contains Model Binding, which is a lot more powerful way of binding data to your models. A great post on this can be found here:
http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx
To replace the simple
BindingHelperExtensions.UpdateFrom() Method you can use the following:
//Old method in preview 4
//BindingHelperExtensions.UpdateFrom(dto, Request.Form);
//New method in preview 5
UpdateModel(dto, Request.Form.AllKeys);
this.ReadFromRequest() has also gone.
The
HttpRequestBase allows you to simply pass the key you want:
query = Request["query"];
LinkBuilder has moved to "Futures"
If you ever used the
LinkBuilder in your code; this can now be found in
Microsoft.Web.Mvc
No more HttpContextWrapper2
In Preview 4 Microsoft had the very well named
HttpContextWrapper2. In Preview 5 this has gone, and you should be able to just use the better named
HttpContextWrapper.
Html.RouteLink() has new overloads
This is where you will need to check your application thoroughly for any unusual links in your pages.
In Preview 4
Html.RouteLink() Extension took three parameters:
- string linkText
- string routeName
- RouteValueDictionary values
In Preview 5 the three parameters have change to be:
- string linkText
- string routeName
- object htmlAttributes
Because
RouteValueDictionary is an
object, your routes dictionary now gets treated as if you wanted to add then as attributes on the link element!
Now I have to add null (for the
htmlAttributes) as a forth parameter like so:
<%= Html.RouteLink("Click Here", "Deafult", new { controller="Home", action = "Index"}, null)%>
Build MvcContrib
My application uses the MvcContrib. Right now not all test pass and therefore there is not a official release on the MvcContrib for Preview 5. However, the project is building and you can download the source from here:
http://mvccontrib.googlecode.com/svn/branches/Preview5
Is that everything?
I managed to get my application working with the above changes, however there were sections of code for my admin section that uses it's own
ViewLocator that I had to comment out to build. I have not quite figured out the new changes to the
ControllerBase and
IController....watch this space.
Hope your
ASP.NET MVC Preview 5 application works sucessfully!
Passing a
querystring to a named route in
ASP.NET MVC is not well documented.
I stumbled across this by mistake! Using either the
Html.RouteLink extention or the
RedirectToRoute method it is possible to pass any number of
querystring parameters to the route.
All you have to do is pass the parameter in the
RouteValueDictionary. For it to appear on the
querystring the parameter name must not appear on the named route in the
RouteCollection.
This is easier to explain in code!
Route (in
Global.ascx.cs):
routes.MapRoute(
"Default",
"{controller}/{action}/{id}"
);
using Html.RouteLink:
<%= Html.RouteLink("Click Me!", "Default", new { controller = "Home", action = "Index", id = "1234", myparameter = "hello" }) %>
using RedirectToRoute:
return RedirectToRoute("Default", new {controller = "Home", action = "Index", id = "1234", myparameter = "hello"});
The above both direct to:
http://www.mywebsite.com/Home/Index/1234?myparameter=hello
I previously blogged about
Javascript Intellisence for Google maps.
I asked the question: "If I get enough interest in this intellisense file I will keep developing (adding to) it. Let me know what you think and what you want to see in the next version."
Well a few of you responded and the project is now on CodePlex:
http://www.codeplex.com/GMapJS
Thanks to
Nicolas Boonaert for setting this up...and for getting the project off the ground.
Hope you find this useful and hopefully soon you will see more Google Map Classes added soon.
I love
ActiveRecord and
NHibernate as ORMs. They do exactly as it says on the tin. I love the fact that I can develop an application in a DDD (Domain Driven Development) fashion and almost forget about the fact that I need a relational database.
I also love the fact that I don't have to write lengthy Stored Procedures to get data back....but there is always an application out there where this has to change.
I currently working on a new project that requires a lot of reporting and data warehousing, so it has come to the point where I will require to pull out my SQL Books and remember what a Stored Procedure is!
Ok...writting Stored Procedures is like riding a bike, once you get started again it all comes flooding back. However, I still want to use
ActiveRecord as my ORM as 90% of database work can be handled by my standard data repository.
I want a nice way to call a a method in my repository, pass the SP name, some parameters and then return a type safe list of objects.
Solution
This is what I ended up with:
var parameters = new Dictionary<string, object> { { "@Author", "Joe Bloggs" } };
IList<Book> bookList = Repository.ExecuteSqlProc<Book>("sp_GetBooks", parameters);
I know this example is really simple; so simple in fact that you would not use a SP for this, but it does show calling a SP and then mapping back to the
ActiveRecord object. What is really cool is that if you enable Lazy loading you can then get all the nested objects back no problem.
Right this is how it's done:
1 public virtual IList<T> ExecuteSqlProc<T>(string sqlProc, IDictionary<string, object> parameters)
2 {
3 var targetType = typeof(T);
4
5 var holder = ActiveRecordMediator.GetSessionFactoryHolder();
6 var config = holder.GetConfiguration(holder.GetRootType(targetType));
7 var session = config.BuildSessionFactory().OpenStatelessSession();
8
9 var parameterNames = GetParameterNames(sqlProc);
10
11 IQuery query;
12 try
13 {
14 query = session.GetNamedQuery(sqlProc);
15 }
16 catch (MappingException)
17 {
18 var paramlist = string.Empty;
19
20 foreach (var parameterName in parameterNames)
21 {
22 paramlist += ":" + parameterName +", ";
23 }
24
25 paramlist = paramlist.TrimEnd(new[] {' ', ','});
26
27 var sqlQueryMapping = @"<sql-query name='{0}'><return class='{1}' />EXEC dbo.{0} {2}</sql-query>";
28
29 var sqlQuery = string.Format(sqlQueryMapping, sqlProc, targetType.Name, paramlist);
30
31 var mapping_hbm_xml =
32 string.Format(@"<hibernate-mapping xmlns='{0}' assembly='{1}' namespace='{2}'>{3}</hibernate-mapping>",
33 Configuration.MappingSchemaXMLNS, targetType.Assembly.FullName, targetType.Namespace, sqlQuery);
34
35 config.AddXmlString(mapping_hbm_xml);
36
37 session = config.BuildSessionFactory().OpenStatelessSession();
38 query = session.GetNamedQuery(sqlProc);
39 }
40
41 foreach (var parameterName in parameterNames)
42 {
43 if(parameters.ContainsKey(parameterName))
44 {
45 query.SetParameter(parameterName, parameters[parameterName]);
46 }
47 else
48 {
49 query.SetParameter(parameterName, "null" );
50 }
51 }
52
53 return query.List<T>();
54 }
55
56 private static readonly Dictionary<string,string[]> parameterlist = new Dictionary<string, string[]>();
57 private static string[] GetParameterNames(string sqlProc)
58 {
59 if (!parameterlist.ContainsKey(sqlProc))
60 {
61 var session = new ARContext().Session;
62 IList<string> returnObj = new List<string>();
63 IDbConnection conn;
64 IDbCommand cmd = null;
65
66 try
67 {
68 conn = session.Connection;
69 cmd = conn.CreateCommand();
70 cmd.CommandText =
71 "SELECT p.name FROM sys.objects AS o INNER JOIN sys.parameters AS p ON o.object_id = p.object_id WHERE o.object_id = OBJECT_ID('" +
72 sqlProc + "')";
73 cmd.CommandType = CommandType.Text;
74
75 using (IDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
76 {
77 while (reader.Read())
78 {
79 returnObj.Add(reader.GetString(0));
80 }
81 }
82 }
83 catch (Exception ex)
84 {
85 throw new ActiveRecordException("Could not perform GetParameters for " + sqlProc, ex);
86 }
87 finally
88 {
89 if (cmd != null) cmd.Dispose();
90 }
91
92 parameterlist.Add(sqlProc, returnObj.ToArray());
93 }
94
95 return parameterlist[sqlProc];
96
97 }
98
99 }
Does any of this make sense or do I need to explain!?
Hope this helps.
When I allow
NHibernate to generate the schema for my object graph I get an issue with foreign key constraints on collections.
I'm I can't be the only person that has come across this problem!? I'll try and outline it for you. Ps. At the end of this post I do have a solution!
I have an abstract base class that has a simple
IList<string>
public abstract class VariationBase : DomainBase
{
public IList<string> OtherVariations { get; set; }
}
Then I have a number of other classes that inherit from
VariationBase (The idea being that each class could have a title variation for example).
When
NHibernate creates the SQL to create the schema it creates a foreign key constraint on the first class that it comes across.
The problem with this is that if I were to insert a new object that was not the class that the constrain is on I will get an foreign key constraint violation.
Solution 1.
After
NHibernate has created the Schema go back into SQL and remove the constraint manually.
This is not great because every time you generate the schema you must remember to remove this constraint, and this could happen a lot during development!
Solution 2.
When I came across this before I put
inverse=true on my mapping for the collection to generate the schema, then after it had been generated put
inverse back to
false.
This still has the same issue as before in the fact you have to "remember" to do this every time you generate the schema. Also if you are using the latest trunk version of
NHibernate then this method won't work as the line that checks
IsInverse before creating the foreign key constraint has been commented out (I'm sure there is a reason!).
Solution 3.
Add another attribute to the collections mapping in
NHibernate so that you can stipulate
constrain=false. By doing so will tell
NHibernate not to create the foreign key constraint on that collections table. This is the preferred method as once the work in
NHibernate is done I no longer have to worry about it.
You can download the patch that adds this functionality
here.
Remember that if you use this patch that you will have to re-generate the Cfg/MappingSchema/Hbm.generated.cs using the HbmXsd tool (NHibernate.Tool.HbmXsd).
I have also included a patch for
ActiveRecord so that you can add this property to your collection attribute e.g. (notice the
Constrain = false Property):
public abstract class VariationBase : DomainBase
{
[HasMany(typeof(string), ColumnKey = "Original", Table = "OtherVariations", Constrain = false, Element = "Variation", Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList<string> OtherVariations { get; set; }
}
I was wondering if anyone else has come across this problem? Or if there is a better solution that is already in place?
I'm thinking about submitting these patches to the relevant people to be committed into the trunks of
NHibernate and
ActiveRecord, but I'm not sure if it is useful enough and would be used?
Let me know what you think I should do...is it worth submitting?
Microsoft have a project on CodePlex
to fully enable JavaScript Intellisense for the Virtual Earth Map Control inside of Visual Studio 2008. Which you can find here.
This makes working with VE really easy.
I have noticed a few people (on forums etc) wishing for JavaScript intellisense for Google Maps. so I have created a js file that contains the information to enable this.
You can download this file here.
If you don't know what to do with this file check out Scott Gu's Blog on VS 2008 JavaScript Intellisense.
The basics is to place the js file in you
JavaScript folder and reference the file like so:
/// <reference path="googlemaps-intellisense.js" />
Please note that the js file contains NO functional Google Maps code, so you will still need to setup all the necessary links to the Google Maps API.
The Google Maps API is huge and sadly I have not been able to add every single Mapping object, but all the main ones are there.
If I get enough interest in this intellisense file I will keep developing (adding to) it. Let me know what you think and what you want to see in the next version.
Hope this helps.
I have a simple
ActiveRecord class:
[ActiveRecord]
public class Employee
{
[PrimaryKey(PrimaryKeyType.GuidComb)]
public Guid? Id { get; set; }
[Property]
public string FirstName { get; set; }
[Property]
public string LastName { get; set; }
}
I then create a create/edit form on my UI. To update the database is easy with the
ASP.NET MVC Framework and
ActiveRecord:
In my controller:
public void Update(Guid? Id)
{
var emp = DomainFactory.Get<Employee>(Id);
BindingHelperExtensions.UpdateFrom(emp, Request.Form);
emp.Save();
//Render View
}
Ok now I want to add a
Department Object to the
Employee:
[BelongsTo(Cascade = CascadeEnum.SaveUpdate)]
public Department Department { get; set; }
On my form page I create a select dropdown with a list of Departments. The value of the select options is the
Guid Id of the
Department.
MVC does not know anything about
ActiveRecord so it cannot convert the
Guid (actually it is of type
string in the Forms Collection) to type of
Department.
In order to continue using the
UpdateFrom Binder method we need to create a
TypeConverter for the
ActiveRecord Objects:
1 public class ARConverter<T> : TypeConverter
2 {
3 public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
4 {
5 if (sourceType == typeof(string))
6 {
7 return true;
8 }
9
10 return base.CanConvertFrom(context, sourceType);
11 }
12
13 public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
14 {
15
16 if (value.GetType() == typeof(string))
17 {
18 return ActiveRecordMediator.FindByPrimaryKey(typeof(T), new Guid((string) value));
19 }
20 return base.ConvertFrom(context, culture, value);
21 }
22 }
All I need to do is decorate my
ActiveRecord classes with this
TypeConverter:
[ActiveRecord]
[TypeConverter(typeof(ARConverter<Department>))]
public class Department
Now when
MVC updates from the Forms Collection it will convert the Id to the actually object from the database.