WebApi & Bundling Optimization In MVC3 Project

14/02/2013 Leave a comment

If you are interested in using  WebApi and Bondling  features in your MVC3 project this post is for you. Fortunately, WebApi and Bondling both have been implemented in individual packages  and are not depends on MVC 4 framework so your are able to use them in your mvc3 project.

Let install following package by Nuget:

Microsoft.AspNet.WebApi

Microsoft.AspNet.Web.Optimization

These packages bring WebApi and Bundling to your project. Easy!!! But still there are few steps to go to make it a lovely solution.

WebApi

Routing mapping is the first step to have a great WebApi combination in our project. I love the way that MVC 4 organized its stuff so lets add a folder to the project and name it App_Start. Add WebApiConfig  file to this folder containing following code:

public static class WebApiConfig
    {
        public static string DefaultApi = "DefaultApi";

        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: DefaultApi,
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            // Comment this line if you want to response as a XML
            GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
        }
    }
 }

Its the same code you can find in a MVC4 project and its a place to define and map all your webapi routs. If you want  have change default XML serialization to JSON, you should have the last line of thie code in Register method otherwise you must comment it. As you can see, by default WebApi routes start with a “api/” .

Now, lets add a new class in a new file  to the folder with following content:

    public class RouteConfig
    {
        public static string Default = "Default";

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: Default,
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }

I just extracted and moved the routing configuration to a separated class. By this way it would be easier to manage and maintain.

Third file in the folder is FilterConfig:


    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
    }

Its going to manage our filters in a separated class and file to keep everything clean and tidy.

Last file in this folder would BondleConfig and I will talk about that soon in Bundling.

In the next step we should update the Global.asax.cs file as following:

public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            // confign webapi settings
            WebApiConfig.Register(GlobalConfiguration.Configuration);

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

            // confign mvc website's routing settings
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            // config bundling settings
            // set  debug="false" in   in web.config to have optimization
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

Now we have a nice and tidy start up class which is calling all our configuration class one by one and set up the application. It is done, WebApi is ready to go so lets to create a folder as WebApi in the project and add out first WebApi controller.

 public class PersonController : ApiController
    {
        // GET api/person
        public List Get()
        {
            return DB.Persons;
        }

        // GET api/person/1
        public Person Get(int id)
        {
            var person= DB.Persons.Single(p => p.Id == id);
            if (person != null) return person;
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }

        // POST api/person
        public HttpResponseMessage Post([FromBody] Person person)
        {
            DB.Persons.Add(person);

            // Compose location header that tells how to get this person
            // e.g. ~/api/person/5
            var response = Request.CreateResponse(HttpStatusCode.Created, person);
            response.Headers.Location =  new Uri(Url.Link(WebApiConfig.DefaultApi, new { id = person.Id }));

            return response;
        }

        // PUT api/person/1
        public HttpResponseMessage Put([FromBody] Person person)
        {
            var response = new HttpResponseMessage(HttpStatusCode.NoContent);

            var existingPerson = DB.Persons.SingleOrDefault(p => p.Id == person.Id);
            if (existingPerson != null)
            {
                existingPerson.Name = person.Name;
            }
            else
            {
                response = new HttpResponseMessage(HttpStatusCode.NotFound);
            }

            return response;
        }

        // DELETE api/person/1
        public HttpResponseMessage Delete(int id)
        {
            var response = new HttpResponseMessage(HttpStatusCode.NoContent);

            var existingPerson = DB.Persons.SingleOrDefault(p => p.Id == id);
            if (existingPerson != null)
            {
                DB.Persons.Remove(existingPerson);
            }
            else
            {
                response = new HttpResponseMessage(HttpStatusCode.NoContent);
            }

            return response;
        }
    }

DB is a fake class that provides us a list of person for testing. I don’t go in the details for the WebApi actions (Mehtods) and leave it for later.

Bundling & Optimization

To use bundling facilities in MVC3 lets add a new class in App_Start folder with the following code to config our bundles.

        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {

            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                        "~/Scripts/jquery-ui-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new StyleBundle("~/bundles/css").Include("~/Content/site.css"));

            bundles.Add(new StyleBundle("~/bundles/themes/base/css").Include(
                        "~/Content/themes/base/jquery.ui.core.css",
                        "~/Content/themes/base/jquery.ui.resizable.css",
                        "~/Content/themes/base/jquery.ui.selectable.css",
                        "~/Content/themes/base/jquery.ui.accordion.css",
                        "~/Content/themes/base/jquery.ui.autocomplete.css",
                        "~/Content/themes/base/jquery.ui.button.css",
                        "~/Content/themes/base/jquery.ui.dialog.css",
                        "~/Content/themes/base/jquery.ui.slider.css",
                        "~/Content/themes/base/jquery.ui.tabs.css",
                        "~/Content/themes/base/jquery.ui.datepicker.css",
                        "~/Content/themes/base/jquery.ui.progressbar.css",
                        "~/Content/themes/base/jquery.ui.theme.css"));
        }
    }

I hope you know how bundling works otherwise please have look at here.

Also we have to update _Layout.cshtml  to you our bundle as well.

@using System.Web.Optimization


<meta charset="utf-8" />
@ViewBag.Title

    @Styles.Render("~/bundles/css")
    @Scripts.Render("~/bundles/modernizr")</pre>
<div class="page"><header>
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">@Html.Partial("_LogOnPartial")</div>
<nav>
<ul id="menu">
	<li>@Html.ActionLink("Home", "Index", "Home")</li>
	<li>@Html.ActionLink("About", "About", "Home")</li>
</ul>
</nav></header><section id="main">@RenderBody()</section><footer></footer></div>
<pre>    @Scripts.Render("~/bundles/jquery")

    @RenderSection("scripts", required: false)

To use bundle helper class you have to add the its namespace to the page as following which is not a nice idea.

@using System.Web.Optimization

Undoubtedly, updating web.config file in View folder is a better solution. so you should add System.Web.Optimization to the list in system.web.webPages.razor section.

I hope you enjoy these lovely features in your project. you can download the sample project form here

Categories: MVC 3 Tags: , , , ,

Ninject Dependency Resolver For Web API

06/12/2012 Leave a comment

I just found an great implementation of Ninject dependency resolver by Brad Wilson for Web API. you can have  here

Categories: Uncategorized

A Glance At ASP.NET MVC 4 Project Templates in Visual Studio 2012

17/08/2012 Leave a comment

Visual studio 2012 and .Net framework 4.5 was released yesterday so it’s a good time to take a look at new MVC framework (MVC 4) included in VS2012. If you are a interested in trying out, you will be able to download Express or  90 days trial version from here.

MVC 4 Projects
MVC 4 Application in Visual Studio 2012 exposes  6 different types of templates (projects) . Please let me to introduce you with them here.

MVC4 Project Types

MVC4 Project Types

Empty Application
Provides the minimum references and resources required to run an Asp.net MVC application.  As you can see  in below,  Models, Controllers, App_Data are completely empty folders.

MVC4 Empty Application Structure

MVC4 Empty Application Structure

App_Start folder which is new in MVC4 contains 3 configuration files. It is including  FilterConfig.cs, RouteConfige.cs and WebApiConfig.cs.  These classes are responsible for application configuration when your application is starting.  In fact, FilterConfig and RoutrConfig are not really new. RegisterGlobalFilters and RegisterRoutes methods have been extracted from MVCApplication class in Global.acax file and put in these separated files.

Refrences folder has been changed as well.  Entity Framework which was included in MVC3 has been vanished. Instead, Json.Net has been added. Also, Http programming has been empowered  by adding System.Net.Http class family. In Addition System.Web.WebPages family has been got richer by adding  System.Web.WebPages.Deployment and System.Web.WebPages.Rezore.

MVC3 Empty Application Structure

MVC3 Empty Application Structure

Views folder  just includes a Web.config file at the time being means _ViewStart.cshtml and Shared folder(including _Layout.cshtml & Error.cshtml) have been disappeared since  MVC3. Content and Scripts folders have been removed as well.

Basic Application
It’s a new project type in MVC 4 and it was not available in MVC3.  I personally think that Basic project is much much closer structurally to Empty project in MVC3. It includes Content and Scripts as well as few more references. Here is a short list of what’s included

Bundling and minimization facilities have been prepared in this template. BundleConfig.cs file has been added to App_Start folder. Additionally, what had been disappeared in Views folder came back to the board. _Layout.cshtml  includes the jQuery bundle as well as the default theme styling.

MVC4 Basic Application Structure

MVC4 Basic Application Structure

Internet Application
Adds tow controllers( Account controller and Home controller)  to the Basic template with implemented actions and views.  Membership management functionality which allows you register, login, change password and so on is implemented in Account controller and Home controller gives you Index, About and Contact actions working with their own related views. Its a template used usually to start a normal web project in action.

MVC4 Internet Application Structure

MVC4 Internet Application Structure

AuthConfig.cs in App_Start  helps you to allow your users log in using their accounts from other sites such as Microsoft, Facebook, and Twitter. Thanks to DotNetOpenAuth class family.  Account views have been empowered by adding few views and partial views to make it easy for you to have an external log in by other sites account in your websites.

Intranet Application
In fact, It’s  the Internet Application except for Membership management.  the Account controller and the web.config has been configured  to use Windows as it’s authentication method.

Mobile Application
Mobile website programming is one of  most important feature in MVC 4 so this template has everything that Internet Application template has, however it  is using  jQuery.mobile instead. In addition,  DotNetOpenAuth references for external log in functionality is removed.

MVC4 Mobile Application Structure

MVC4 Mobile Application Structure

Web API  Application
Its another new Template in VS2012 to make it easy to develop RESTful web services and applications to feed a vast variety rage of clients from desktop browsers to tablet applications. It allows you to expose your data and service to the web directly over  Http for more details visit here. This template includes everything from Basic Template expect Account controller and membership functionality and references However Value controller as a simple API example jumps in.

MVC4 Web API Application Structure

MVC4 Web API Application Structure

MVC 4 in Visual studio 2012 caters a wider range of  project templates which help developer to do their job easier and faster as well as following best practices and keeping development rules.

Thanks to VS2102 development team. Well done guys!

ASP.NET MVC 4, Browser-Specific Views

15/08/2012 1 comment

Introduction

In this post I am going to write about an interesting and powerful feature in ASP.NET MVC 4 , View Overriding or Browser- Specific Views. But, what does it mean?!  It’s a  lovely new feature that lets you to override views ,  layouts and partial views  globally or individually for mobile devices or  a specific  browser such as iPhone’s safari. MVC4 aims at mobiles and tables devices so it’s a good support  to develop a mobile version for  your website or even more such as a  particular version for iPhone or iPad.

Requirement

  1. Visual Studio Express 2010 SP1
  2. ASP.NET MVC 4 RC
  3. Windows 7 Phone Emulator
  4. Apple Safari Browser

Getting Start

Start by running Visual Studio  and select New Project from the Start page. In New Project window, choose ASP.NET MVC4 Web Application.

VS - New Project Window

New Project Window

Keep going by choosing Mobile Application in New ASP.NET MVC 4 Project  window then OK.

New ASP.NET MVC 4 Project

New ASP.NET MVC 4 Project

Visual Studio Creates the project and you are able to run it immediately.

Our Project

You can go around and have a look at other pages (About & Contact)  as well. It looks perfect, doesn’t it? Thanks to jQuery Mobile which is bringing an awesome mobile experience to the website.

As you can see, all tools and facilities have been prepared by MVC 4  to develop a mobile web application with a nice and familiar appearance.

Lets modify the first page (Views/Home/index.cshtml)  as following:

@{
    ViewBag.Title = "Home Page";
 }</pre>
<h2>Welcome,</h2>
<pre>
You are visiting our website on your <strong>Desktop</strong> computer</pre>
<ul data-role="listview" data-inset="true">
	<li data-role="list-divider">Navigation</li>
	<li>@Html.ActionLink("About", "About", "Home")</li>
	<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
<pre>

Now, if you run the project again, the following screen shot will be what you can see

View on desktop

View On Desktop

View Overriding:

To provide a mobile-specific view,  you can copy a view file and add .Mobile to the file name. so copy Views\Home\Index.cshtml to Views\Home\Index.Mobile.cshtml.

Then, please modify Index.Mobile.cshtml file as following:

@{
ViewBag.Title = "Home Page";
 }</pre>
<h2>Welcome,</h2>
<pre>
You are visiting our website on your <strong>Mobile</strong> device</pre>
<ul data-role="listview" data-inset="true">
	<li data-role="list-divider">Navigation</li>
	<li>@Html.ActionLink("About", "About", "Home")</li>
	<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
<pre>

When you are running the project on your  desktop, there is on change but lets to check it on  Windows 7 Phone Emulator .

As you can see, the mobile version of our view (Index.Mobile.cshtml) has been rendered. That means MVC 4 is able to detect the client agent automatically.

Browser-specific View

Are you interested in developing defferent specific views for some specific! clients such as iPhone or iPad!? Not a big deal. Copy the view file and add .iphone or .ipad to the file name. So copy Views\Home\Index.cshtml to Views\Home\Index.iphone.cshtml and do the same for Index.ipad.cshtml. Modify the files to have a proper content as following:

For iPhone in Index.iphone.cshtml file:

@{
ViewBag.Title = "Home Page";
 }</pre>
<h2>Welcome,</h2>
<pre>
You are visiting our website on your <strong>iPhone</strong></></pre>
<ul data-role="listview" data-inset="true">
	<li data-role="list-divider">Navigation</li>
	<li>@Html.ActionLink("About", "About", "Home")</li>
	<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
<pre>

For iPad in Index.ipad.cshtml:

@{
ViewBag.Title = "Home Page";
 }</pre>
<h2>Welcome,</h2>
<pre>
You are visiting our website on your <strong>iPad</strong></pre>
<ul data-role="listview" data-inset="true">
	<li data-role="list-divider">Navigation</li>
	<li>@Html.ActionLink("About", "About", "Home")</li>
	<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
<pre>

In the next step you should modify Global.asax file, so add a new private method and name it registerDisplayMode. Here’s the complete method:

private void registerDisplayMode(string agent, int index = 0)
 {
      DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode(agent)
      {
             ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
                                   (agent, StringComparison.OrdinalIgnoreCase) >= 0)
      });
 }

Then call this method in Application_Start method as following:

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

            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            registerDisplayMode("iPhone", 0);
            registerDisplayMode("iPad", 1);
        }

Also, you have to add following line to the using section of Global.asax

using System.Web.WebPages;

Now, you have registered your new display mode for two individual browser agents (iPhone & iPad) so those will be matched against each incoming request. If the request come form an iPhone or iPad (user agent contains the string “iPhone” or “iPad”), MVC will look for views whose name contains the “iPhone” or “iPad” suffix. You well be able to test it in Apple Safari by changing its agent to iPhone or iPad (more details).

iphone view

iPhone View

iPad View

iPad View

Mvc4 supports you  to switch between different views base on the user agent just with few lines codding and  jQuery Mobile provides a familiar mobile experience  on your website for users.

To be continued …

Source code is available here.

Categories: MVC 4 Tags: