Best asp.net-mvc questions in December 2010

Where does the "business logic layer" fit in to an MVC application?

21 votes

First, before anyone screams dupe, I had a hard time summarizing it in a simple title. Another title might have been "What is the difference between a domain model and MVC model?" or "What is a model?"

Conceptually, I understand a Model to be the data used by the views and controller. Beyond that, there seems to be a great deal of differing opinions on what makes up the model. What's a domain model, versus an app model, vs a view model, vs a service model, etc..

For example, in a recent question I asked about the repository pattern, I was told point blank that the repository is part of the model. However, I have read other opinions that the model should be seperated from the persistence model and the business logic layer. After all, isn't the Repository pattern supposed to decouple the concrete persistence method from the model? Other people say there is a difference between the Domain model and the MVC model.

Let's take a simple example. The AccountController that is included with the MVC default project. I've read several opinions that the Account code included is of poor design, violates SRP, etc.. etc.. If one were to design a "proper" Membership model for an MVC application, what would that be?

How would you seperate the ASP.NET services (Membership provider, role provider, etc..) from the model? Or would you at all?

The way I see it, the model should be "pure", perhaps with validation logic.. but should be seperate from business rules (other than validation). For example, let's say you have a business rule that says someone must be emailed when a new account is created. That doesn't really belong in the model in my view. So where does it belong?

Anyone care to shed any light on this issue?

The way I have done it - and I'm not saying it is right or wrong, is to have my View and then a model that applies to my view. This model only has what is relevant to my view - including data annotations and validation rules. The controller only houses logic for building the model. I have a service layer which houses all business logic. My controllers call my service layer. Beyond that is my repository layer.

My domain objects are housed separately (in their own project, actually). They have their own data annotations and validation rules. My repository validates the objects in my domain before saving them into the database. Because every object in my domain inherits from a base class which has validation built in, my repository is generic and validates everything (and requires it inherits from the base class).

You might think that having two sets of models is duplication of code, and it is to an extent. But, there are perfectly reasonable instances where the domain object is not appropriate for the view.

Case in point is when working with credit cards - I have to require a cvv when processing a payment, but I cannot store the cvv (it is a $50,000 fine to do so). But, I also want you to be able to edit your credit card - change of address, name, or expiration date. But you aren't going to give me the number or the cvv when editing it, and I certainly am not going to put your credit card number in plain text on the page. My domain has these values required for saving a new credit card because you give them to me, but my edit model doesn't even include the card number or cvv.

Another benefit to so many layers is that if architected correctly, you can use structuremap or another IoC container and swap out pieces without detrimentally affecting your application.

In my opinion, controller code should only be code targeted at the view. Show this, hide that, etc. The service layer should house the business logic for your app. I like having all of it in one place so it's easy to change or tweak a business rule. The repository layer should be relatively dumb - devoid of business logic and only query your data and return your domain objects. By separating the view models from the domain model, you have much more flexibility when it comes to custom validation rules. It also means you don't have to dump every piece of data into your view in hidden fields and push it back and forth between the client and server (or rebuild it on the backend). Your view model will then house only the information relevant to the view - and it can be customized to have bools for view logic or counts or enums so that the view itself isn't cluttered up with complicated logic statements like

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && 
    Model.SomeObject.SomeInt == 3 && ...) { %>

While everything seems spread out and over-layered, it has a purpose for being architected this way. Is it perfect? not really. But I do prefer it to some past designs of calling repositories from the controller and having business logic mixed in the controller, repository, and model.

Upgraded to MVC 3 RTM: CS0103: The name 'View' does not exist in the current context

17 votes

I have just updated to ASP.NET MVC 3 RC2.

The sample app I am working on now produces the following error, whenever a cshtml view is rendered:

CS0103: The name 'View' does not exist in the current context

It fails on the line:

@{
   View.Title = "MyView";
}

... and fails anywhere else it encounters View in the code on the Razor file.

I have copied the web.config from a new apps View folder to my sample app, but the problem persists.

A brand new application runs without problems.

I have also rebuilt the solution, run Clean Solution. No joy.

I haven't worked on the sample for a few days. So it might be an issue that has nothing to do with RC2...

It's been renamed 'ViewBag'. You can read more about the changes from RC1 -> RC2 here

ASP.NET MVC Razor: How to render a Razor Partial View's HTML inside the controller action

11 votes

How to generate a HTML of a given partial view on ASP.NET view engine is known.

But if this functionality is used on razor partial view it does not work, as exception says the partial view does not derive from "UserControl".

How to fix the rendering to support razor partial view?

I need this because I generate emails form this partial views ...

UPDATE:

Code that fails (@mcl):

public string RenderPartialToString(string controlName, object viewData)
    {
        ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
        viewPage.Url = this.GetUrlHelper();

        string fullControlName = "~/Views/Email/" + controlName + ".ascx";

        viewPage.ViewData = new ViewDataDictionary(viewData);
        viewPage.Controls.Add(viewPage.LoadControl(fullControlName));

        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter tw = new HtmlTextWriter(sw))
            {
                viewPage.RenderControl(tw);
            }
        }
        return sb.ToString();
    }

@Html.Partial("nameOfPartial", Model)

Update

protected string RenderPartialViewToString(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = ControllerContext.RouteData.GetRequiredString("action");

    ViewData.Model = model;

    using (StringWriter sw = new StringWriter()) {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

Source: http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/

ASP.NET MVC 3 Razor Templates VS RenderPartial

11 votes

Hi Guys,

I just read this blog post on Razor Templating in ASP.NET MVC 3.

Put simply, i just dont get it!

That is, i don't see why we need this (fairly) complicated code to achieve what can be done IMO easier (and neater) with @RenderPartial ?

Here's what i don't like:

  1. The template is stored as a Func<T,HelperResult> delegate?
  2. That template delegate is persisted in the Controller ViewData (e.g HttpContext.Current.Items)

The only "benefit" i read from that blog is that a seperate file isn't required for templating, meaning you don't need to re-compile etc.

But i don't see that as a valid argument. Extra files are fine as long as the solution organization isn't compromised.

I prefer using @RenderPartial, as i can keep my markup seperate from the master view, and i can render this both inline (render time) and with jQuery (e.g AJAX event).

Maybe i'm missing something here, but can anyone give some reasons why we should choose Razor Templating over RenderPartial to create re-usable content?

Well, you should ask the author of that post about his motivation for presenting this technique.

It certainly illustrates what is possible in Razor. Whether you should use it is a different matter. I personally think that there are alternative techniques that are less complicated (I agree with your points about storing a Func inside of the request context).

  • There's @RenderPartial which you already mentioned.
  • You can also use the @helper syntax (either as a local helper or a global helper)
  • You can write an html helper (and use TagBuilder to assemble the output)
  • You can write a child action
  • You can write a templated helper

Now that I look at the above list I think MVC might provide too much choice :)

Update To better illustrate how inline templates can be useful I wrote a blog post about using them to call sections with default code: Optional Razor Sections with Default Content.

You can use it to write something like this:

@this.RenderSection("OptionalSection", @<div>Default Content</div>) 

Why would multiple simultaneous AJAX calls to the same ASP.NET MVC action cause the browser to block?

9 votes

A few days back I asked this question:

Why does $.getJSON() block the browser?

I fire six jQuery async ajax requests at the same controller action pretty much all at once. Each request takes 10 seconds to return.

Through debugging and logging requests to the action method I notice that the requests are serialised and never run in parallel. i.e. I see a timeline in my log4net logs like this:

2010-12-13 13:25:06,633 [11164] INFO   - Got:1156
2010-12-13 13:25:16,634 [11164] INFO   - Returning:1156
2010-12-13 13:25:16,770 [7124] INFO   - Got:1426
2010-12-13 13:25:26,772 [7124] INFO   - Returning:1426
2010-12-13 13:25:26,925 [11164] INFO   - Got:1912
2010-12-13 13:25:36,926 [11164] INFO   - Returning:1912
2010-12-13 13:25:37,096 [9812] INFO   - Got:1913
2010-12-13 13:25:47,098 [9812] INFO   - Returning:1913
2010-12-13 13:25:47,283 [7124] INFO   - Got:2002
2010-12-13 13:25:57,285 [7124] INFO   - Returning:2002
2010-12-13 13:25:57,424 [11164] INFO   - Got:1308
2010-12-13 13:26:07,425 [11164] INFO   - Returning:1308

Looking at the network timeline in FireFox I see this:

alt text

Both the log sample above and the Firefox network timeline are for the same set of requests.

Are requests to the same action from the same page serialised? I'm aware of serialised access to the Session object in the same session, but no session data is being touched.

I stripped the client side code down to a single request (the longest running one) but this still blocks the browser, i.e. only when the ajax request completes does the browser respond to any link clicking.

What I also observe here (in Chrome's developer tools) is that upon clicking on a link when a long running ajax request is executing it reports a Failed to load resource error immediately which suggests that the browser has killed (or is attempting to kill and waiting?) the ajax request:

alt text

However the browser still takes an age to redirect to the new page.

Are ajax requests really asynchronous or is this sleight of hand because javascript is actually single threaded?

Are my requests just taking too long for this to work?

The problem occurs in Firefox and IE as well.

I also changed the script to use $.ajax directly and explicitly set async: true.

I'm running this on IIS7.5, both the Windows 2008R2 and Windows 7 flavours do the same thing.

Debug and release builds also behave the same.

The answer was staring me in the face.

ASP.NET Session State Overview

*Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished.

Annoyingly I'd skimmed paragraph this a couple of weeks ago not really taking in the full impact of the bold sentences. I had read that simply as "access to session state is serialised" and not "all requests, no matter whether you touch session state or not, are serialised" if the requests came from the same session.

Fortunately there is a work around in ASP.NET MVC3 and its possible to create session-less controllers. Scott Guthrie talks about these here:

Announcing ASP.NET MVC 3 (Release Candidate 2)

I installed MVC3 RC2 and upgraded the project. Decorating the controller in question with [SessionState(SessionStateBehavior.Disabled)] solves the problem.

And of course typically I just found this in Stack Overflow a few minutes ago:

Asynchronous Controller is blocking requests in ASP.NET MVC through jQuery

ASP.NET MVC - Posting a form with custom fields of different data types

8 votes

In my ASP.NET MVC 2 web application, I allow users to create custom input fields of different data types to extend our basic input form. While tricky, building the input form from a collection of custom fields is straight-forward enough.

However, I'm now to the point where I want to handle the posting of this form and I'm not certain what the best way to handle this would be. Normally, we'd use strongly-typed input models that get bound from the various statically-typed inputs available on the form. However, I'm at a loss for how to do this with a variable number of input fields that represent different data types.

A representative input form might look something like:

  • My date field: [ date time input control ]
  • My text field: [ text input field ]
  • My file field: [ file upload control ]
  • My number field: [ numerical input control ]
  • My text field 2: [text input field ]
  • etc...

Ideas I've thought about are:

  • Sending everything as strings (except for the file inputs, which would need to be handled specially).
  • Using a model with an "object" property and attempting to bind to that (if this is even possible).
  • Sending a json request to my controller with the data encoded properly and attempting to parse that.
  • Manually processing the form collection in my controller post action - certainly an option, but I'd love to avoid this.

Has anyone tackled an issue like this before? If so, how did you solve it?

Update:

My "base" form is handled on another input area all together, so a solution doesn't need to account for any sort of inheritence magic for this. I'm just interested in handling the custom fields on this interface, not my "base" ones.

Update 2:

Thank you to ARM and smartcaveman; both of you provided good guidance for how this could be done. I will update this question with my final solution once its been implemented.

This is how I would begin to approach the issue. A custom model binder would be pretty easy to build based on the FormKey property (which could be determined by the index and/or label, depending).

public class CustomFormModel
{
    public string FormId { get; set; }
    public string Label { get; set; }
    public CustomFieldModel[] Fields { get; set; }
}
public class CustomFieldModel
{
    public DataType DateType { get; set; } //  System.ComponentModel.DataAnnotations
    public string FormKey { get; set; }
    public string Label { get; set; }
    public object Value { get; set; }
}
public class CustomFieldModel<T> : CustomFieldModel
{
    public new T Value { get; set; }
}

Also, I noticed one of the comments below had a filtered model binder system. Jimmy Bogard from Automapper made a really helpful post about this method at http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/17/a-better-model-binder.aspx , and later revised in, http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/11/19/a-better-model-binder-addendum.aspx . It has been very helpful for me in building custom model binders.

Update

I realized that I misinterpreted the question, and that he was specifically asking how to handle posting of the form "with a variable number of input fields that represent different data types". I think the best way to do this is to use a structure similar to above but leverage the Composite Pattern. Basically, you will need to create an interface like IFormComponent and implement it for each datatype that would be represented. I wrote and commented an example interface to help explain how this would be accomplished:

public interface IFormComponent
{
    //  the id on the html form field.  In the case of a composite Id, that doesn't have a corresponding 
    //  field you should still use something consistent, since it will be helpful for model binding
    //  (For example, a CompositeDateField appearing as the third field in the form should have an id 
    //  something like "frmId_3_date" and its child fields would be "frmId_3_date_day", "frmId_3_date_month",
    //  and "frmId_3_date_year".
    string FieldId { get; }

    //  the human readable field label
    string Label { get; }

    //  some functionality may require knowledge of the 
    //  Parent component.  For example, a DayField with a value of "30"
    //  would need to ask its Parent, a CompositeDateField
    //  for its MonthField's value in order to validate
    //  that the month is not "February"
    IFormComponent Parent { get; }

    //  Gets any child components or null if the 
    //  component is a leaf component (has no children).
    IList<IFormComponent> GetChildren();

    //  For leaf components, this method should accept the AttemptedValue from the value provider
    //  during Model Binding, and create the appropriate value.  
    //  For composites, the input should be delimited in someway, and this method should parse the 
    //  string to create the child components.  
    void BindTo(string value);

    //  This method should parse the Children or Underlying value to the 
    //  default used by your business models.  (e.g. a CompositeDateField would 
    //  return a DateTime.  You can get type safety by creating a FormComponent<TValue>
    //  which would help to avoid issues in binding.
    object GetValue();

    //  This method would render the field to the http response stream.
    //  This makes it easy to render the forms simply by looping through 
    //  the array.  Implementations could extend this for using an injected 
    //  formatting 
    void Render(TextWriter writer);
} 

I am assuming that the custom forms can be accessed via some sort of id which can be contained as a form parameter. With that assumption, the model binder and provider could look something like this.

public interface IForm : IFormComponent
{
    Guid FormId { get; }
    void Add(IFormComponent component);
}
public interface IFormRepository
{
    IForm GetForm(Guid id);
}
public class CustomFormModelBinder : IModelBinder   
{
    private readonly IFormRepository _repository;
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult result;
        if(bindingContext.ValueProvider.TryGetValue("_customFormId", out result))
        {
            var form = _repository.GetForm(new Guid(result.AttemptedValue));
            var fields = form.GetChildren();
            //  loop through the fields and bind their values 
            return form;
        }
        throw new Exception("Form ID not found.");
    }
}

Obviously, all the code here is just to get the point across, and would need to be completed and cleaned up for actual use. Also, even if completed this would only bind to an implementation of the IForm interface, not a strongly typed business object. (It wouldn't be a huge step to convert it to a dictionary and build a strongly typed proxy using the Castle DictionaryAdapter, but since your users are dynamically creating the forms on the site, there is probably no strongly typed model in your solution and this is irrelevant). Hope this helps more.

Aspx to Razor syntax converter?

8 votes

I have a considerable amount of ASPX and ASCX files writed in C# for MVC and I would like to convert them to the new Razor syntax.

Any body knows about some utility that makes this job faster?

I've written a small piece of code that makes the conversion. I think it could be useful to somebody else. I've learned a lot about regex's balancing goup definitions on the way.

    public static class RazorConversor
{
    public static void ConvertAll(string directory)
    {
        string[] array = Directory.GetFiles(directory, "*.aspx", SearchOption.AllDirectories).Concat(
                         Directory.GetFiles(directory, "*.ascx", SearchOption.AllDirectories)).ToArray();

        foreach (var fileName in array)
        {
            string aspxCode = File.ReadAllText(fileName);
            string razorCode = ConvertToRazor(aspxCode);
            File.WriteAllText(fileName, razorCode); //rename manually to update .csproj & source control
        }
    }

    static readonly string[] DefaultNamespaces = new string[]
    {
        "System.Web.Helpers", 
        "System.Web.Mvc",
        "System.Web.Mvc.Ajax",
        "System.Web.Mvc.Html",
        "System.Web.Routing",
        "System.Web.WebPages",
    };

    public static string ConvertToRazor(string aspxCode)
    {
        return ConvertToRazor(aspxCode, DefaultNamespaces); 
    }

    public static string ConvertToRazor(string aspxCode, string[] defaultNamespaces)
    {
        //namespaces
        string text2 = Regex.Replace(aspxCode, @"<%@\s+Import Namespace=""(?<ns>.*?)""\s+%>",
            m => defaultNamespaces.Contains(m.Groups["ns"].Value) ? null : "@using " + m.Groups["ns"].Value);

        //headers
        string text3 = Regex.Replace(text2, @"<%@\s(?<dir>.*?)%>", m =>  "@{ " + m.Groups["dir"].Value + "}"); // Preserves headers

        //expressions 
        string text4 = Regex.Replace(text3, @"<%[=:](?<expr>.*?)%>", m =>
        {
            string expr = m.Groups["expr"].Value.Trim();
            string cleanExpr = Regex.Replace(expr, @"(""(\\""|[^""])*"")|(@""([^""]|"""")*"")|(\([^\(\)]*(((?'Open'\()[^\(\)]*)+((?'Close-Open'\))[^\(\)]*)+)*\))", m2 => "");
            return cleanExpr.Contains(' ') ? "@(" + expr + ")" : "@" + expr;
        }, RegexOptions.Singleline);

        //code blocks
        string text5 = Regex.Replace(text4, @"<%(?<code>.*?)%>", m =>
        {
            string code = m.Groups["code"].Value.Trim();

            Dictionary<string, string> stringLiterals = new Dictionary<string,string>();

            code = Regex.Replace(code, @"(""(\\""|[^""])*"")|(@""([^""]|"""")*"")", m2 =>
            {
                string key = "<$" + stringLiterals.Count + "$>";
                stringLiterals.Add(key, m2.Value);
                return key;
            }); 

            string result = Regex.Replace(code, 
                @"((?<blockHeader>(else|(for|switch|foreach|using|while|if)\s*\([^\(\)]*(((?'Open'\()[^\(\)]*)+((?'Close-Open'\))[^\(\)]*)+)*\))\s*)" + 
                @"((?<fullBlock>{[^{}]*(((?'OpenCurly'{)[^{}]*)+((?'CloseCurly-OpenCurly'})[^{}]*)+)*})|(?<openblock>{.*))|" + 
                @"(?<text>((?!({|}|\s)(for|switch|foreach|using|while|if|else)(\s|{|\()).)+))",
                m2 =>
                {
                    if(m2.Value.Trim().Length == 0 || m2.Value.StartsWith("else")|| m2.Value.StartsWith("}"))
                        return m2.Value;

                    if(m2.Groups["text"].Success)
                        return "@{ " + m2.Value.Trim() + "}\r\n"; 

                    return "@" + m2.Value; 
                }, RegexOptions.ExplicitCapture | RegexOptions.Singleline);

            result = Regex.Replace(result, @"<\$\d+\$>", 
                m2 => stringLiterals[m2.Value]);

            return result;
        }, RegexOptions.Singleline);

        return text5; 
    }
}

ASP.NET MVC to ignore ".html" at the end of all url

8 votes

Hi All,

I am new to asp.net mvc and now struggling with url routing. I'm using asp.net mvc 3 RC2.

How can I create a url routing that IGNORES the very end extension in url. the extension can be: .html, .aspx, .php, .anything.

For example, these urls:

/Home.html
/Home.en
/Home.fr
/Home

should go to Home controller?

one more example:

/Home/About.html
/Home/About.en
/Home/About.fr
/Home/About

should go to Home controller and About action.

thank you :)

I'm not sure if you're using IIS7, but if so, then I would recommend a rewrite rule which checks for urls ending in .xyz and then doing a rewrites for them without the .xyz.

Something like this:

<rewrite>
  <rules>
    <rule name="HtmlRewrite">
      <match url="(.*)(\.\w+)$" />
      <action type="Rewrite" url="{R:1}" />
    </rule>
  </rules>
</rewrite>

This will handle the use cases you suggested. Anything that ends with an extension and some characters will be rewritten to a url without the extension. The benefit of this is that you will only need one route because everything goes into your application without one.

Implementing UnitOfWork with Castle.Windsor

8 votes

Simple question.

How do I use UnitOfWork with Castle.Windsor, nHibernate, and ASP.NET MVC?

Now for the extended details. In my quest to understand the UnitOfWork pattern, I'm having difficulty coming across anything that uses a direct example in conjunction with Castle.Windsor, specifically in regards to the way it needs to be installed.

Here is my understanding so far.

IUnitOfWork

  • The IUnitOfWork interface is used to declare the pattern
  • The UnitOfWork class must Commit and Rollback transactions, and Expose a Session.

So with that said, here is my IUnitOfWork. (I am using Fluent nHibernate)

public interface IUnitOfWork : IDisposable
{
    ISession Session { get; private set; }
    void Rollback();
    void Commit();
}

So here is my Castle.Windsor Container Bootstrapper (ASP.NET MVC)

public class WindsorContainerFactory
{
    private static Castle.Windsor.IWindsorContainer container;
    private static readonly object SyncObject = new object();

    public static Castle.Windsor.IWindsorContainer Current()
    {
        if (container == null)
        {
            lock (SyncObject)
            {
                if (container == null)
                {
                    container = new Castle.Windsor.WindsorContainer();

                    container.Install(new Installers.SessionInstaller());
                    container.Install(new Installers.RepositoryInstaller());
                    container.Install(new Installers.ProviderInstaller());
                    container.Install(new Installers.ControllerInstaller());
                }
            }

        }

        return container;
    }
}

So now, in my Global.asax file, I have the following...

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        // Register the Windsor Container
        ControllerBuilder.Current
            .SetControllerFactory(new Containers.WindsorControllerFactory());
    }

Repository

Now I understand that I need to pass the ISession to my Repository. So then, let me assume IMembershipRepository.

class MembershipRepository : IMembershipRepository
{
   private readonly ISession session;
   public MembershipRepository(ISession session)
   {
      this.session = session;
   }

   public Member RetrieveMember(string email)
   {
      return session.Query<Member>().SingleOrDefault( i => i.Email == email );
   }
}

So I am confused, now. Using this method, the ISession doesn't get destroyed properly, and the UnitOfWork never gets used.

I've been informed that UnitOfWork needs to go in the Web Request Level - but I cannot find anything explaining how to actually go about this. I do not use a ServiceLocator of any sort ( as when I tried, I was told this was also bad practice... ).

Confusion -- How does a UnitOfWork get created?

I just don't understand this, in general. My thought was that I would start passing UnitOfWork into the Repository constructors - but if it has to go in the Web Request, I'm not understanding where the two relate.

Further Code

This is extra code for clarification, simply because I seem to have a habit of never providing the right information for my questions.

Installers

public class ControllerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            AllTypes.FromThisAssembly()
            .BasedOn<IController>()
            .Configure(c => c.LifeStyle.Transient));
    }
}

public class ProviderInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component
            .For<Membership.IFormsAuthenticationProvider>()
            .ImplementedBy<Membership.FormsAuthenticationProvider>()
            .LifeStyle.Singleton
        );
    }
}

public class RepositoryInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component
            .For<Membership.IMembershipRepository>()
            .ImplementedBy<Membership.MembershipRepository>()
            .LifeStyle.Transient
        );

        container.Register(
            Component
            .For<Characters.ICharacterRepository>()
            .ImplementedBy<Characters.CharacterRepository>()
            .LifeStyle.Transient
        );
    }
}

public class SessionInstaller : Castle.MicroKernel.Registration.IWindsorInstaller
{
    private static ISessionFactory factory;
    private static readonly object SyncObject = new object();

    public void Install(Castle.Windsor.IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<ISessionFactory>()
                .UsingFactoryMethod(SessionFactoryFactory)
                .LifeStyle.Singleton
            );

        container.Register(
            Component.For<ISession>()
            .UsingFactoryMethod(c => SessionFactoryFactory().OpenSession())
            .LifeStyle.Transient
        );
    }

    private static ISessionFactory SessionFactoryFactory()
    {
        if (factory == null)
            lock (SyncObject)
                if (factory == null)
                    factory = Persistence.SessionFactory.Map(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["Remote"].ConnectionString);
        return factory;
    }
}

UnitOfWork

Here is my UnitOfWork class verbatim.

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory sessionFactory;
    private readonly ITransaction transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
        Session = this.sessionFactory.OpenSession();
        transaction = Session.BeginTransaction();
    }

    public ISession Session { get; private set; }

    public void Dispose()
    {
        Session.Close();
        Session = null;
    }

    public void Rollback()
    {
        if (transaction.IsActive)
            transaction.Rollback();
    }

    public void Commit()
    {
        if (transaction.IsActive)
            transaction.Commit();
    }
}

Your NH Session is a Unit of Work already http://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.aspx

So I'm not sure why you would ever need to abstract this out any further. (if anyone reading this answer know's why I would be happy to hear, I've honestly never heard of any reason why you would need to...)

I would implement a simple Session Per Request. I don't know how you would do that with Windsor since I've never used it, but with It's rather simple with StructureMap.

I wrap the structuremap factory to hold my session factory and inject the session into the repositories as required.

    public static class IoC
    {
        static IoC()
        {
            ObjectFactory.Initialize(x =>
            {
                x.UseDefaultStructureMapConfigFile = false;

                // NHibernate ISessionFactory
                x.ForSingletonOf<ISessionFactory>()
                 .Use(new SessionFactoryManager().CreateSessionFactory());

                // NHibernate ISession
                x.For().HybridHttpOrThreadLocalScoped()
                 .Use(s => s.GetInstance<ISessionFactory>().OpenSession());

                x.Scan(s => s.AssembliesFromApplicationBaseDirectory());
            });

            ObjectFactory.AssertConfigurationIsValid();
        }

        public static T Resolve<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }

        public static void ReleaseAndDisposeAllHttpScopedObjects()
        {
            ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
        }
    }

In the global.asax file on Request_End I call the ReleaseAndDisposeAllHttpScopedObjects() method.

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            IoC.ReleaseAndDisposeAllHttpScopedObjects();
        }

So the session is opened when I call my first repository, and when the request is ended it's disposed of. The repositories have a constructor which takes ISession and assigns it to a property. Then I just resolve the repo like:

var productRepository = IoC.Resolve<IProductRepository>();

Hope that helps. There are many other ways of doing it, this is what works for me.

Ninject.Web.MVC + MVC3 throws StackOverflowException

7 votes

I've got a simple web application using ASP.NET MVC3 and Ninject.Web.MVC (the MVC3 version).

The whole thing is working fine, except when the application ends. Whenever it ends, the kernel is disposed, as seen in Application_End() in NinjectHttpApplication:

Reflector tells me this:

public void Application_End()
{
    lock (this)
    {
        if (kernel != null)
        {
            kernel.Dispose();
            kernel = null;
        }
        this.OnApplicationStopped();
    }
}

What happens is that my webserver goes down with a StackOverflowException (I tried both IIS7 and the built-in webserver in VS2010). I can only assume this is where it's going wrong, as I haven't written any code myself on application end.

I figured out that the Kernel knows how to resolve IKernel (which returns the Kernel itself), might this be something that could cause the stack overflow? I could imagine something like this happens:

  • Kernel.Dispose()
  • Dispose all instances in the kernel
  • hey! look at this, the kernel is also in the kernel. Return to step 1.

In other words, the kernel gets disposed, disposes all references it holds (which includes a self-reference), which causes it to dispose itself.

Does this make any sense?

Edit:

It seems the problem is in NinjectHttpApplication. Take a look at this activation code:

    public void Application_Start()
    {
        lock (this)
        {
            kernel = this.CreateKernel();
            ...
            kernel.Bind<IResolutionRoot>().ToConstant(kernel).InSingletonScope();
            ...
        }
    }

It seems ok, but what's happening now is that whenever an IResolutionRoot is called, kernel is cached within itself. When disposing the kernel, the cache is emptied which disposes all cached objects, which causes a circular reference.

A simple solution for NinjectHttpApplication would be to simply change the binding. Change the constant binding to a method one:

kernel.Bind<IResolutionRoot>().ToConstant(kernel).InSingletonScope();

becomes

kernel.Bind<IResolutionRoot>().ToMethod(x => this.Kernel);

This solves the problem, but I am not sure if the whole circular dispose caching issue is a bug in ninject.

I encountered the same issue.

I ended up copying the code for NinjectHttpApplication and removing Kernel.Dispose() in the Application_End function.

public void Application_End()
{
    lock (this)
    {
        if (kernel != null)
        {
            //kernel.Dispose();
            kernel = null;
        }
        this.OnApplicationStopped();
    }
}

That should fix the error. Not sure if there is a planned fix for it though.

Which is better: HTML rendering on server or on client in JS?

7 votes

I have a best practices/performance question. I am creating an ASP.NET MVC 2 project, and I have several parts of the page that are accessed dynamically either at load time or on user interaction.

My question is this: is it better to have the sections rendered in HTML on the server and then just replace the sections of HTML or is it better to just retrieve the information as JSON objects and then use JS to create and insert the HTML?

It should be noted that the objects of concerns are very simple in nature. An example would be a 'message' object that has an ID field, a to field, a from field, a subject field and a body field that are all strings.

Are there some serious advantages or disadvantages to either approach? Or is this a case of preference to how to construct your application?

I don't think either are better; it's going to depend on your requirements. The question is borderline unanswerable. Are you using the data on the client for further computation or manipulation or are you just plopping something out to be displayed?

In both cases you're outputting textual data, though it happens to be easier to represent data structures as JSON more directly than it is to convert data structures to HTML and it's easier to directly display HTML than JSON.

ASP.NET MVC Service vs Repository

7 votes

Hi,

What is the difference between a service layer and a repository? I have worked through a lot of demo MVC apps and most of them have just repositories. And some have a mixture of both. When do you use just repositories and when do you use services / or both?

he repositories act just as gateways to your data storage (sql database, xml file etc.) while the services usually implement some business rules on your data before sending the data to be saved in the database via a repository.

consider this example:

class UserRepository : IUserRepository
{
   public void Create(User userToCreate)
   {
       //update tracking and save to repository
       _userToCreate.DateCreated = DateTime.Now;
       _dataContext.AddNew(userToCreate);
   }
}


class UserService : IUserService 
{
   private IUserRepository _repository;

   public UserService(IUserRepository repository)
   {
        _repository = repository;
   }

   public void Create(User createdByUser, User userToCreate)
   {
       //implement some business rules
       if(!createdByUser.HasRights(UserRights.CanCreateNewUser))
           throw new Exception("This user '"+createdByUser.Name+"' does not have the rights to create a new user");

       //update rules auditing
       _userToCreate.CreatedByUserId = createdByUser.Id;

       //save entity to repository
       _repository.Create(userToCreate);
   }
}

Then in your Controller action you will use the service directly where all your business rules can be applied. That way you can test you controllers, business rules (services) and persistence (repositories) separately/independently using mocks.

    public ActionResult CreateUser(User newUser)
    {
        if(ModelState.IsValid)
        {
           _userService.Create(this.CurrentUser, newUser);
           if(newUser.Id > 0)
               return RedirectToAction("UserCreated");
        }
        return View(newUser);
    }

MVC3 RC Razor @helper locations

7 votes

In the introduction to Razor on ScottGu's blog, he mentioned placing the @helpers inside Views\Helpers. I tried doing so in the RC and after a lot of searching, I found out that the helpers should be in the App_Code folder. I don't need my helpers in another assembly (especially if they're specific to this project), and having them way up in the App_Code seems ugly IMO. Is there a current solution to have the these helpers inside a View\Helpers folder?

I am afraid they didn't yet implement this feature yet, at least not in the RC build.

ASP.NET MVC - How to maintain ModelState from a different controller?

7 votes

I have a HomeController with an Index action that shows the Index.aspx view. It has a username/password login section. When the user clicks the submit button, it POSTs to a Login action in the AccountController.

        <% Html.BeginForm("Login", "Account", FormMethod.Post); %>

In that action, it tests for Username/Password validity and if invalid, sends the user back to the Login page with a message that the credentials were bad.

    [HttpPost]
    public ActionResult Login(LoginViewModel Model, string ReturnUrl)
    {
        User user = MembershipService.ValidateUser(Model.UserName, Model.Password);
        if (user != null)
        {
            //Detail removed here
            FormsService.SignIn(user.ToString(), Model.RememberMe);
            return Redirect(ReturnUrl);
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
        // If we got this far, something failed, redisplay form
        return RedirectToAction("Index", "Home");  // <-- Here is the problem.  ModelState is lost.
    }

But here's the problem: the ValidationSummary is always blank because we're losing the Model when we RedirectToAction.

So the question is: How do I send the user to the action on a different controller without a Redirect?

As others have said it's common to return the view if validation fails but as you are calling from your account controller you will want to specify the full path of your view

return View("~/Views/Home/Index.aspx", model);

Or

It is also common to have a seperate login page and redirect to that page if the login fails. Both pages will submit to the same login action. Facebook does this for example.

Or

As you only want to display an error message

return RedirectToAction("Index", "Home", new { LoginAttempts = 1 });

then in your Index action read the LoginAttempts parameter and choose to display the error message accordingly.

How do I remain DRY with asp.net mvc view models & data annotation attributes?

6 votes

How do I remain DRY with asp.net mvc view models & data annotation (validation, display, and data modeling) attributes with Asp.Net MVC? I have passed model objects as well as action specific view models to views. I find both directions to have some issues with trying to remain DRY.

  • Use model objects as your view model: This works fine in simple situations and allows you to only write data annotation attributes once, on each model object. The problem arises when you have complex views that require more than one object type. The resulting view model architecture is a mishmash of using view model classes and actual model classes. Additionally, this method can expose model properties to your view that you do not intend.

  • Use a unique view model class per action: The view model class only contains view specific properties, decorated with data annotation attributes. In my experience, this method has not proved to be very DRY, as data annotation attributes tend to get duplicated across view model classes. For example, New and Edit view models share a lot, but not all, of properties and data annotations.

How do I remain DRY with asp.net mvc view models & data annotation attributes?

So far, I've found that using inheritance to combine shared properties works best. I'm using a unique view class per action and am pretty happy with the solution so far. It doesn't solve 100% of the cases, but it does cover the majority and almost eliminates duplicate data contract attributes.

asp.net mvc validation must be a number custom error

5 votes

Hi,

I am new to asp.net and I have a problem. When the users insert in a editor for a decimal field something other than numbers, they get an error "Field name" is not a number. But I don't want them to receive this message I want them to receive another message. I have no problem with this with required and range validators. Is there any way for me to do this?

I am not refering necessarily to changing the culture just displaying another message.

Thanks.

This is the actual answer:

create a class CustomClientDataTypeModelValidatorProvider copy the code from the MVC sources change the method MakeErrorString to output the appropiate message like this:

private static string MakeErrorString(string displayName)
            {
                return String.Format(CultureInfo.CurrentCulture, Core.Resources.Errors.EroareNuENr, displayName);
            }

I couldn't find a way not to copy the code just extend it as it uses this static method. If anyone knows this please tell me.

The in global asax I wrote this:

var cdProvider = ModelValidatorProviders.Providers.SingleOrDefault(p => p.GetType().Equals(typeof(ClientDataTypeModelValidatorProvider)));
            if(cdProvider != null)
            {
                ModelValidatorProviders.Providers.Remove(cdProvider);
                ModelValidatorProviders.Providers.Add(
                        new CustomClientDataTypeModelValidatorProvider());
            }

so that the flow would actually be routed to my class and not the class in the asp.net MVC dll

I got the idea from here: