Area in MVC - giving a nice physical structure & dealing with template bug

In my last blog post I talked about ‘retrieving views from different folders in MVC’ and it works cool when we want view pages always inside Views folder (which is on the project root) but our requirement not ends here.

The new version "Area in MVC 5" is available here.

Introduction

As you know MVC Architecture separates all the logics: model logic, business logic and presentation logic and provides a very clean and light weight application in total. One more good thing that I love is, it provides logical separation physically also. In physical logic separation controllers, models and views are kept in another folder on root with the help of Area. Areas provide a way to separate a large MVC Web Application into smaller functional groupings inside MVC Application and each group contains MVC Structure (Ex. Model, View and Controller folders). Area was introduced with MVC2 release.

Now, let’s talk about a requirement

Assume, you are working on a MVC Project where you have to work on account section, administrative section, support section, billing section and so on. In this case you should use Area which will provide a strong physical structure. See how it looks like.


You can see every section has MVC Architecture Controller, Model, View (view will have a Shared folder where you can place your layouts, partial views etc) and an AreaRegistration (which contains RegisterArea method similar to RegisterRoutes).

How to Create It

Here I’m going to create CRUD views for Students inside Area. I will take the advantage of EF Code First. Let’s walk through the simple steps.

Step 1

Right click on Project and then pick Add|Area.


Step 2

Now this will bring a dialog-box. Type the Area name which is similar to section name (you can see it in first image, Admin, Billing, Support).


I typed ‘Student’, and hit Add button.

Step 3

You will see following structure.


Step 4

As I said, I am going to take the advantage of EF Code first so I need a model class, here it is.

public class StudentViewModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
}

Step 5

In this step I will name the controller ‘Student’ and in template select ‘MVC controller with read/write actions and views, using Entity Framework’. Also, select model class which is Student and then create a new DbContext by name StudentContext, finish with clicking on Add button.


In the next step we will run the application but before this you should check this entry in Global.asax file, it should be there on the top.

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

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    AuthConfig.RegisterAuth();
}

Step 6

Now we are all set to run the project and I expect your app should run, if not don’t throw bricks on me.

Well, in my case I fall in an error. I noticed a nice bug (because I love bugs) in product template. (I will figure out this error in Step 7), you just keep reading:

An error occurred creating the configuration section handler for system.web.webPages.razor/host: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)


Notice in above image I’m trying to navigate http://localhost:33103/Student/Student. In this URL, the first ‘Student’ segment is my area name and second ‘Student’ segment is my controller name.

Why I’m passing controller name and can we make it default?

Keep reading, you will get your answers.

Let’s open StudentAreaRegistration.cs (find this file in ‘Student’ area) file.


Open this file and look at the codes.

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Student_default",
        "Student/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional }
    );
}

You can see I am registering a new area and in the route we have following URL format:

"Student/{controller}/{action}/{id}"

Notice following things:

i) Controller is preceded by ‘Student’ which is area name.
ii) In above RegisterArea we have default value for action and id is optional.
iii) We don’t have default value for controller.

If you want to provide default controller name, do it this way.

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Student_default",
        "Student/{controller}/{action}/{id}",
        new { controller = "Student", action = "Index", id = UrlParameter.Optional }
    );
}

Now, only hitting http://localhost:33103/Student URL will work, because we hardcoded the controller value.

Step 7

I figured out the issues that we experienced in step 6. When I opened the Web.config file which is inside Areas|Student|Views|Web.config, I found some really strange entries for WebPageVersion and MvcVersion. I will call this MVC Template bug which is in product.


And here is the workaround:

i) Find ‘__WebPagesVersion__.0.0’ and replace it with ‘2.0.0.0’.
ii) Find ‘__MvcVersion__.0.0’ and replace it with ‘4.0.0.0’.

Do a build and try running.


Yah! It is running now and the only thing left is its presentation layout.

Step 8

To apply layout, I’ll simply copy the _ViewStart.cshtml file, look at the image.
[Tip: To copy it, drag the file by pressing Ctrl Key in Solution Explorer]


Now, try running and enjoy.


Hope this helps.

Comments

  1. I am new for MVC so i want basic concept of MVC

    ReplyDelete
  2. Area
    I am finding difficulties to arrange the area folder for my project
    This is Job application website and having mainly following type of pages/section

    1) - Admin Pages - Only for Admin user(site owners) - so only authenticated(logged in) admin users case see those pages/section
    example - Post_Jobs_Page, Edit_Job_Page, Change_Admin_Password, Add_News_Events_Page etc.

    2) - Job seeker Pages - only for Job seekers - so only authenticated(logged in) Job Seeker users case see those pages/section
    example - change_Password, Edit_Profile, Applied_Jobs etc

    3) - Common Pages - where any job seeker either authenticated(logged in) or without authentication can visit those page
    Search_Jobs, ContactUs, AboutUs etc

    So I am not sure how to organize MVC folder structure - how may areas should i add and where to put which files

    ReplyDelete

Post a Comment

Popular posts from this blog

Migrating database from ASP.NET Identity to ASP.NET Core Identity

Customize User's Profile in ASP.NET Identity System