Home > MVC 3 > WebApi & Bundling Optimization In MVC3 Project

WebApi & Bundling Optimization In MVC3 Project

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

Advertisements
Categories: MVC 3 Tags: , , , ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: