Just tried to build Sharp Architecture through hornget:

horn.exe –install:sharp.architecture

It failed with the message “The type or namespace name 'AutoMap' does not exist in the namespace 'FluentNHibernate' (are you missing an assembly reference?)” and 16 errors with the same message. All I needed to do was to open the SharpArch.sln in c:\users\<my username>\.horn\frameworks\sharp.architecture\working\src\sharparch and Resharper immediately told me to add a using statement to FluentNHibernate.Automapping. Seems like they’ve changed namespace in fluent nhibernate from FluentNHibernate.AutoMap to FluentNHibernate.Automapping. After changing this and made sure that I could compile the solution I just ran the horn command line tool again and it built everything successfully. Just remember to revert the changes or wipe the folder clean so there wont be any conflicts the next time…

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

AutoMapper is a convention-based object-object mapper as described by the AutoMapper project homepage (http://www.codeplex.com/AutoMapper).

Basically it will map properties between two different objects (different types). If the name of the properties are the same it just works. It works with lists and nested types. All you need to do is initiate the mapping and then do the actual mapping. Here’s an example when mapping from an instance of type User to a UserViewModel instance.

   1: Mapper.CreateMap<User, UserViewModel>;
   2: User user = new UserRepository().Get(1);
   3: UserViewModel userViewModel = Mapper.Map<User, UserViewModel>();

If the structure/name isn’t something that AutoMapper can figure out how to map then it’s possible to add manual mappings with lambda expressions. For example if the User has a Telephone type with a property called PhoneNumber and the UserViewModel has a basic string property called Phone:

   1: Mapper.CreateMap<User, UserViewModel>()
   2:     .ForMember(viewModel => viewModel.Phone, opt => opt.MapFrom(user => user.Telephone.PhoneNumber)));
   3:  
   4:  

Very cool stuff indeed. I introduced AutoMapper in one of the projects I’m currently working on and since it was mostly 1-1 mapping that was done, I reduced over 600 lines of code in two hours in the project. Since I just replaced the body of my mapper methods with the call to AutoMapper that meant that all the unit tests I had written could verify that everything worked as before.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Currently I’m building a image gallery component for a website where the user is able to upload images and they are displayed in a gallery using http://pikachoose.com. I have one action on my controller called Download which takes the id of the image that should be downloaded as an argument. It worked fine using this code (in the beginning):

   1: public ActionResult Download(int id)
   2: {
   3:     var image = Repository.GetById(id);
   4:  
   5:     return File(image.Data, image.ContentType, image.Filename);
   6: }

The problem with this code only showed up with some images. The problem is the last parameter to File(), image.Filename. Which is the filename of the original image the user has uploaded. If the filename contains “invalid characters” ASP.NET MVC throws this exception:

[FormatException: An invalid character was found in the mail header.]
   System.Net.Mime.MailBnfHelper.GetTokenOrQuotedString(String data, StringBuilder builder) 
   System.Net.Mime.ContentDisposition.ToString() +270
   System.Web.Mvc.FileResult.ExecuteResult(ControllerContext context) +164

 

The part that confused me was “in the mail header”. Suppose they’re reusing some mail component for mime parsing. To fix it I only had to make sure that the filename didn’t had any invalid characters, I did it by setting it to the filename I use on the server instead of the filename submitted by the user.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

When using the automapping feature of Fluent NHibernate you may encounter some problems when storing large text data in the database. Below is a class which gets mapped by the automapper in Fluent NHibernate. Both Title and TextContent are strings. The difference between them is that the TextContent property might store a large chunk of text.

image

The default automapper in Fluent NHibernate will create a table with a nvarchar(255) column for both the Title and TextContent. This is fine for most cases but in this case the TextContent property may contain much more than 255 characters. Trying to save the entity with more than 255 characters stored in TextContent will give throw an exception saying:

System.Data.SqlClient.SqlException: String or binary data would be truncated.
The statement has been terminated.

This is the same problem you might run into when using Castle ActiveRecord which also will do a default nvarchar(255) for a string property. It's quite simple to override the default automapper in Fluent NHibernate to change the column in the database into a text type for example. All you need to do is create a class which implements the interface IAutoMappingOverride<T> and add it to the configuration.

   1: public class HeadlineOverride : IAutoMappingOverride<Headline>
   2: {
   3:         public void Override(AutoMap<Headline> mapping)
   4:         {
   5:             mapping.Map(t => t.TextContent).CustomTypeIs("StringClob").CustomSqlTypeIs("text");
   6:         }
   7: }


All you need to do a manual mapping of the field and set the custom type to StringClob and SqlType to text. All the other properties will still be mapped by the automapper in Fluent NHibernate. To make sure that Fluent NHibernate will load the override into the configuration you need to set it up.

   1: return AutoPersistenceModel
   2:        .MapEntitiesFromAssemblyOf<Headline>()
   3:        .Where(t => t.Namespace == "Incendi.Models")
   4:        .UseOverridesFromAssemblyOf<HeadlineOverride>();

On line #4 it tells the automapper to use the overrides from the assembly where HeadlineOverride is declared. If you drop/create the schema with this updated configuration you'll end up with a text type on the TextContent column instead of a varchar(255).

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

In one of my recent projects using ASP.NET MVC (updated to RC2) I was going to use Fluent NHibernate. While using Fluent NHibernate I also needed Castles NHibernate Facility for session management, which would simplify the management of sessions in the repositories in the project. It wasn't as easy as I'd hoped to get it all running smoothly.

EDIT: I’d recommend you to use Sharp Architecture (http://code.google.com/p/sharp-architecture/) which is a project template complete with nhibernate+automap, castle windsor and a bunch of other useful things.

1. Castle binaries

First off, get the latest (trunk) Castle binaries from their build server (or build it yourself). You'll need something later than RC3 (which is the version that's available for download as a release) since the IConfigurationBuilder wasn't public before and there was no way of defining a custom configuration builder which we will leverage to be able to hook into the configuration and making sure that automappings are used.

2. Create custom configuration builder

Based upon this excellent post by Mike Hadlow we're creating a custom configuration builder. This is where the magic from Fluent NHibernate comes into play as well.

   1: public class FluentNHibernateConfigurationBuilder : IConfigurationBuilder
   2: {
   3:     public NHibernate.Cfg.Configuration GetConfiguration(IConfiguration facilityConfiguration)
   4:     {
   5:         var defaultBuilder = new DefaultConfigurationBuilder();
   6:         var configuration = defaultBuilder.GetConfiguration(facilityConfiguration);
   7:         
   8:         configuration.AddAutoMappings(AutoPersistenceModel.MapEntitiesFromAssemblyOf<Headline>());
   9:  
  10:         return configuration;            
  11:     }
  12: }

The method AddAutoMappings() on line 8 does all the magic, it's an extension method from Fluent NHibernate which will wire up the normal automappings from Fluent NHibernate. If you want to use the normal Fluent Nhibernate way with manually mapping entities there's a method called AddMappingsFromAssembly() which you should use instead.

3. Setup HttpModule for Castle NHibernate integration

Since we're using Castle NHibernate facility in a web environment we're going to use their httpmodule for managing sessions as well. If you don't manually set it up correctly you will run into issues like "no session or session was closed" with lazy loading when the session is closed. For example if the view is iterating over a list of objects which are supposed to be lazy loaded. With this HttpModule it will take care of it and setup a session per request.

The <httpModules> section of the web.config looks like this with the addition of the new NHibernateSessionWebModule:

<httpModules>
      <add name="ScriptModule" 
           type="System.Web.Handlers.ScriptModule,
                 System.Web.Extensions,
                 Version=3.5.0.0,
                 Culture=neutral,
                 PublicKeyToken=31BF3856AD364E35"
       />
       <add name="UrlRoutingModule" 
            type="System.Web.Routing.UrlRoutingModule,
                  System.Web.Routing,
                  Version=3.5.0.0,
                  Culture=neutral,
                  PublicKeyToken=31BF3856AD364E35"
       />
       <add name="NHibernateSessionWebModule" 
            type="Castle.Facilities.NHibernateIntegration.Components.SessionWebModule,
                  Castle.Facilities.NHibernateIntegration"
       />
</httpModules>

4. Initialize the container

Do something like this in the Application_Start in your HttpApplication class (usually global.asax.cs). The line number 7 sets the controller factory from the mvccontrib project as the default. This means that the controllers will be resolved by castle windsor and all dependencies will also be resolved from the container.

   1: IWindsorContainer container = new WindsorContainer();
   2:  
   3: // Configure the container either by the ordinary config file with XmlInterpreter
   4: // or by fluent like this etc
   5: container.Register(Component.For<IMyComponent>().ImplementedBy<MyComponent>());
   6:  
   7: ControllerBuilder.Current.SetControllerFactory(new MvcContrib.Castle.WindsorControllerFactory(Container)); 

5. Configure Windsor/NHibernate Facility in web.config

First off we add a new <section> to <configSections> in web.config.

<section
  name="castle"
  type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

The <castle> section  is quite large but we'll break it down.

   1: <castle>
   2:   <facilities>
   3:     <facility id="nhibernate"
   4:               isWeb="true"
   5:               type="Castle.Facilities.NHibernateIntegration.NHibernateFacility,
   6:                     Castle.Facilities.NHibernateIntegration"
   7: configurationBuilder="Incendi.Configuration.FluentNHibernateConfigurationBuilder, Incendi">
   8:         
   9:       <factory id="nhibernate.factory" >
  10:         <settings>
  11:           <item key="show_sql">true</item>
  12:           <item key="connection.provider">NHibernate.Connection.DriverConnectionProvider</item>
  13:           <item key="connection.driver_class">NHibernate.Driver.SqlClientDriver</item>
  14:           <item key="dialect">NHibernate.Dialect.MsSql2005Dialect</item>
  15:           <item key="connection.connection_string">Data Source=.\SQLEXPRESS;Initial Catalog=Incendi;Integrated Security=True</item>
  16:           <item key="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</item>
  17:         </settings>
  18:       </factory>
  19:         
  20:     </facility>
  21:   </facilities>
  22:   <components>
  23:     <component id="GenericRepository" type="Incendi.Repositories.Repository`1, Incendi"/>
  24:   </components>
  25: </castle>


On line 4 we tell NHibernate Facility that we'll we using it in a web environment so it can use a special sessionstore for this purpose. Line number 7 indicates that we are specifying a custom configuration builder, which is the one we created in step 2. Make sure the namespace.class, assembly is correct. If you miss this you'll get a not so informative error "classType must be set". Next is the factory where we specify the configuration (if you want some in web.config, in my case I needed the type and connectionstring in the web.config and not specified by Fluent NHibernate since I switch it to SQLite when testing.

Note: I had to add line number 16 after upgrading NHibernate to 2.1

As you can see in the <components> section I've also registered a "GenericRepository" class. This is my base generic repository Repository<T>. There are lots of generic repositories out there, look at Rhino.Commons for example. It's quite easy to write one on your own as well.

6. Using SessionManager from NHibernate Facility in the repository

By setting up NHibernate Facility and retrieving the repository from Windsor which will inject the SessionManager into the Repository. It's now just as easy as calling OpenSession() on SessionManager to get a session. Below is an excerpt from the generic repository I wrote and use in the application to show you how easy it is when you don't need to worry about session management.

   1: public class Repository<T>
   2: {
   3:     private readonly ISessionManager _sessionManager;
   4:  
   5:     public Repository(ISessionManager sessionManager)
   6:     {
   7:         _sessionManager = sessionManager;
   8:     }
   9:  
  10:     public virtual IList<T> GetAll()
  11:     {
  12:         using (var session = SessionManager.OpenSession())
  13:         {
  14:             return session.CreateCriteria(typeof(T)).List<T>();
  15:         }
  16:     }
  17:  
  18:     public virtual T Get(int id)
  19:     {
  20:         using (var session = SessionManager.OpenSession())
  21:         {
  22:             return session.Get<T>(id);
  23:         }
  24:     }
  25: }

 

7. Putting all of it to use with the controllers

For example, I’ve added a UserService component to the castle windsor container which implements IUserservice. The UserController requires a IUserService in the constructor. This dependency will be resolved by castle windsor automatically thanks to the controller factory.

   1: public class UserController : Controller {
   2:     private readonly IUserService _userService;
   3:  
   4:     public UserController(IUserService userService) {
   5:         _userService = userService;
   6:     }
   7: }

Phew, that's a lot of configuration to get it up and running. I hope I didn't forgot anything, drop me a comment if you're having trouble setting it up. Good luck!

Currently rated 1.0 by 2 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

The blog has been down a few times these last couple of weeks with only a "Service Unavailable" error. Been in contact with Surftowns support but they basically only replied "it's back up now when I checked. Could have been a restart or a temporary issue. Sorry.". I suppose it's true as they say: "You get what you pay for".

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Anonymous types

Posted on February 28 by bjn

While reading Jon Skeets book C# in Depth I noticed he mentioned that when using anonymous types it's important that the name and type are the same for the properties. As well as the order. Since the underlying type is using generics it will generate two types when the order of the properties are reversed.

For example, take a look at the following C# code:

var idName = new { Name = "Volvo", Id = 28 };
var idName2 = new { Name = "SAAB", Id = 29 };


What's actually generated under the hood by the compiler looks like this in IL code:

   1: L_0001: ldstr "Volvo"
   2: L_0006: ldc.i4.s 0x1c
   3: L_0008: newobj instance void <>f__AnonymousType4`2<string, int32>::.ctor(!0, !1)
   4: L_000d: stloc.0 
   5: L_000e: ldstr "SAAB"
   6: L_0013: ldc.i4.s 0x1d
   7: L_0015: newobj instance void <>f__AnonymousType4`2<string, int32>::.ctor(!0, !1)
   8: L_001a: stloc.1 


As you can see the type is constructed with the use of generics, where the order of the properties are used. In this example the type will be created with <string, int32>, and both of the objects will be of the same type.

However, if the properties are reversed:

var idName = new { Name = "Volvo", Id = 28 };
var nameId = new { Id = 29, Name = "SAAB" };


The IL code generated is changed:

   1: L_0001: ldstr "Volvo"
   2: L_0006: ldc.i4.s 0x1c
   3: L_0008: newobj instance void <>f__AnonymousType4`2<string, int32>::.ctor(!0, !1)
   4: L_000d: stloc.0 
   5: L_000e: ldc.i4.s 0x1c
   6: L_0010: ldstr "SAAB"
   7: L_0015: newobj instance void <>f__AnonymousType5`2<int32, string>::.ctor(!0, !1)
   8: L_001a: stloc.1 

This time, a new type is generated for the second object where generic initialization is reversed to <int32, string>.

Types are re-used by the compiler within one assembly, but within one assembly it's wise to make sure that the properties are in the same order. Thanks to Resharper life's much easier with their detection of this kind of problems. If you're trying to initialize an anonymous type with the properties reveresed Resharper (I'm using v4.1) pops up and says: "Similar anonymous type detected nearby. Are they the same?"

anontype

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

I've been trying to configure custom error pages for my web application using [HandleError] attributes. While trying to configure my application I've noticed a few things which I thought I should share, which weren't obvious, for me at least.

HandleError is meant to be a way to specify a view to display when a specific exception is thrown. In my case I wanted a "permission denied" view to be displayed when an user didn't have the correct permissions to view/invoke an action on a controller.

So far I've noticed these things:

CustomErrors in web.config must be Off

For the HandleError attribute to intercept the exception the customErrors config value in web.config must be set to Off. Otherwise the exception message and complete stack trace is shown and not the custom view.

Ordering of attributes

The order of the attributes you specify on your controller impacts the way ASP.NET MVC chooses the view to display. For example:

   1: [HandleError]
   2: [HandleError(View = "PermissionDenied", ExceptionType = typeof(PermissionDeniedException))]
   3: public class OCABController
   4:     : Controller
   5: {
   6:     public ActionResult test()
   7:     {
   8:         throw new PermissionDeniedException();
   9:     }
  10: }

The result of the PermissionDeniedTest() method would be that the ASP.NET MVC would display the "PermissionDenied" view. Any other exception and the default "Error" view would be displayed.

The problem is that if you change the order the attributes are specified. For example:

   1: [HandleError(View = "PermissionDenied", ExceptionType = typeof(PermissionDeniedException))]
   2: [HandleError]
   3: public class OCABController
   4:     : Controller
   5: {
   6:     public ActionResult test()
   7:     {
   8:         throw new PermissionDeniedException();
   9:     }
  10: }

Then the default "Error" view would be displayed, just because the order of the HandleError attributes is different.

Don't throw exceptions that would result in an non-HTTP 500 error code

My first attempt for displaying a "PermissionDenied"-view when a user tried to perform something which he didn't had the permission for was to throw an UnauthorizedAccessException. While just trying this out I couldn't get the HandleError attribute to pick up the exception. None of the HandleError attributes picked up the exception and displayed a custom error page. Instead it gave me the call stack and exception message. While debugging the ASP.NET MVC code to try to figure out why it didn't display a custom view I found the answer in HandleErrorAttribute.cs.

   1: // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
   2: // ignore it.
   3: if (new HttpException(null, exception).GetHttpCode() != 500) {
   4:     return;
   5: }

 

Basically it means that any exceptions that would case a non-HTTP 500 error is ignored.

It's possible to decorate a base class with [HandleError]

I've created a base class which inherits from the Controller class. All my controllers inherit from my base controller. This way I can control some common decisions. One of those is which view gets displayed for which exception. In my case I just need to display a "PermissionDenied"-view when a user tries to do something he doesn't have permission to do. Using IAuthorizationFilter to throw a PermissionDeniedException when an user tries to do something which he lacks the permissions to do and setting up an HandleError attribute in my base class with the ExceptionType = typeof(PermissionDeniedException) I can remove some duplicated code and be sure that each Controller behaves the same way.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

As my last post suggested, there is a problem (or bug) in ASP.NET MVC RC1 when adding model errors with AddModelError(string key, string errorMessage) without calling SetModelValue(string key, ValueProviderResult result). Failing to use SetModelValue() to set a value will result in a NullReferenceException with some HtmlHelpers.

A reply on a thread at the asp.net forums by a member of the ASP.NET team:

If you have a custom binder that calls AddModelError() without calling SetModelValue(), the HTML helpers will sometimes throw a NullReferenceException when you try to use them.  The reason is that a call to AddModelError() without a call to SetModelValue() doesn't really mean anything.  Consider that model errors are due to the user submitting bad form data, and by using the HTML helpers you're implicitly telling us that you want them to redisplay the user's invalid submitted form data, but the binder never told us what the bad data was!  It only gave the helpers half the data necessary to render themselves properly; it told them that there was an error, but it didn't provide the expected old value.

Obviously it's not really desirable behavior for us to throw this exception.  We're looking into ways to address this, but choosing an answer isn't as trivial as it seems.  We could silently fall back to a blank value, we could throw a different exception, etc., but in any case we're going to confuse and irritate developers who wrote custom binders and wonder why the users' bad values aren't being propagated between requests.

I've three issues with this. First and foremost the way the AddModelError() and SetModelValue() are linked together, the AddModelError() method wont work if the other method is not invoked and vice versa smells bad to me. It's like setting up an object with a constructor that will create an object in a state where it still needs more data to be functional. My suggestion to fix this issue would be to add another argument to the AddModelError() method, containing the attempted value. This way it's not possible to "forget" to call the SetModelValue() method.

My second issue is the rename of the method from SetAttemptedValue() to SetModelValue(). I dont think the name of the method express it's intent very well. The SetAttemptedValue() is much more clear on what its used for.

The third issue I have is the arguments to the SetModelValue() method.

void SetModelValue(string key, ValueProviderResult result)

The second argument is a ValueProviderResult object. Which has the following constructor:

ValueProviderResult(object rawValue, string attemptedValue, CultureInfo culture)

My issue here is the first argument, object rawValue, what's this? Looking through the source code to ASP.NET MVC RC1 revealed that it's the value that gets converted to a string and then displayed by the HtmlHelpers. The string attemptedValue doesn't get used in that scenario, it only has a few usages in the ASP.NET MVC source code.

In the project I'm currently working on I've created an extension method to the ModelStateDictionary to ease the use of adding a model error. It looks like this:

  1: public static void AddModelError
  2:   (this ModelStateDictionary modelState, string key, string errorMessage, string attemptedValue)
  3: {
  4:   modelState.AddModelError(key, errorMessage);
  5:   modelState.SetModelValue(key, new ValueProviderResult(attemptedValue, attemptedValue, null));
  6: }
This way it's a little bit easier to work with the ModelStateDictionary.AddModelError/SetModelValue methods.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

As my last post indicated, I wasn't sure where SetAttemptedValue on ModelStateDictionary had gone, or what has replaced it. With a little bit of experimenting I noticed that if I used the SetModelValue method, which I suspect is new with 1.0 RC, it would display the input that failed to validate. Which pretty much behaves the same way it was before with SetAttemptedValue(string key, string value). However, there is one difference, if I don't use the SetModelValue I'll get a NullReferenceException from MVC. Before it just displayed the default value. Looking in the source code for MVC 1.0 Release Candidate and Beta 1, I noticed it's been through a major refactoring.

Before in Beta 1, it used the following code to get the attempted value:

string attemptedValue = htmlHelper.GetModelAttemptedValue(name);

And uses the attemptedValue as value for the textbox in my case. Displaying the input the user tried to enter.

However, in 1.0 RC it's gone. Instead it tries to get the value from the model state with the following method:

internal object GetModelStateValue(string key, Type destinationType) {
ModelState modelState;
if (ViewData.ModelState.TryGetValue(key, out modelState)) {
return modelState.Value.ConvertTo(destinationType, null /* culture */);
}
return null;
}

Debugging the application shows the error, the ViewData.ModelState contains the key and returns true. The modelState variable however only contains the list of ModelErrors in Errors (which contains 1 error). The Value is unfortunately null. Which of course will be a NullReferenceException when trying to use

modelState.Value.ConvertTo(destinationType, null)

Probably I've just missed this change in the documentation and it's always been mandatory to set the value in the modelState, but it really shouldn't throw a NullReferenceException.

[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.Mvc.HtmlHelper.GetModelStateValue(String key, Type destinationType) in ...   
System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType  ...
System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Ob...
System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Ob...
System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Ob...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5