Using the Features of ASP.NET MVC 3 Futures

    Introduction:



          ASP.NET MVC 3 includes a bunch of new features that can help you to develop Rich Internet Application(RIA) easily. In addition to these new features, you can also use the features of ASP.NET MVC 3 Futures. ASP.NET MVC 3 Futures includes a bunch of features which may become the part of ASP.NET MVC in future. But you don't have to wait for the future version of ASP.NET MVC to use these features.  In this article, I will show you the features of ASP.NET MVC 3 Futures. I will also show you how to use these features in ASP.NET MVC 3 application. 

 

    Description:

          First of all, you need to download the ASP.NET MVC 3 Futures from Codeplex. Then, create an ASP.NET MVC 3 application and add a reference of Microsoft.Web.Mvc assembly.

 

    CachedDataAnnotationsModelMetadataProvider:

 

           When ASP.NET MVC 3 RC 2 released, it includes a model meta-data provider called CachedDataAnnotationsModelMetadataProvider. This model meta-data provider intended for improving the overall application performance. But this provider has been removed from ASP.NET MVC 3 RTM because it introduced some bugs. Now you can use this provider in ASP.NET MVC 3 application via ASP.NET MVC 3 Futures. For using this provider, just open global.asax file and add the following line in the Application_Start method, 

 

1ModelMetadataProviders.Current = new CachedDataAnnotationsModelMetadataProvider();

 

    New Validation Attributes:

 

          In ASP.NET MVC 3, there is no built-in support for validating email, URL, credit card and file extension. However, through ASP.NET MVC 3 Futures, you can add these validations into your ASP.NET MVC 3 application. For details, see New Validation Attributes in ASP.NET MVC 3 Future.

 

    Model Copier:

 

          In ASP.NET MVC, you often need to copy(or map) the members of your domain model into view model classes, and vice-versa. One way to do this is to use the built-in Object.MemberwiseClone method. But this method has some limitations, such as, you have to do deep copy yourself which is not easy, etc. ASP.NET MVC 3 Futures makes it easy to copy the model members. Here is an example that shows you how to use this feature,

 

01namespace UsingFeaturesASPNETMVC3Futures.Controllers
02{
03    public class ModelCopierController : Controller
04    {
05        public ActionResult Index()
06        {
07            var student = new Student { Age=27, Name="Imran Baloch" };
08            var studentViewModel = new StudentViewModel();
09            ModelCopier.CopyModel(student,studentViewModel);
10            return View(studentViewModel);
11        }
12    }
13}
14namespace UsingFeaturesASPNETMVC3Futures.ViewModels
15{
16    public class StudentViewModel
17    {
18        public int Age { get; set; }
19 
20        public string Name { get; set; }
21    }
22}
23namespace UsingFeaturesASPNETMVC3Futures.DomainModels
24{
25    public class Student
26    {
27        public int Age { get; set; }
28 
29        public string Name { get; set; }
30    }
31}

 

          This is important to note that ModelCopier will only copy the class properties, not the class fields. AutoMapper is recommended for complex mappings.

 

    Html Helpers with Optional Parameters:

 

          HTML helpers are methods that are used to render HTML elements quickly. Currently, the only way to pass attributes to HTML helper methods is through a dictionary or anonymous object. ASP.NET MVC 3 Futures has HTML helper methods which accept their legal attributes as optional parameter. In order to use these HTML helpers, you just need to import Microsoft.Web.Mvc.Html namespace in web.config,     

 

1<add namespace="Microsoft.Web.Mvc.Html"/>

 

          

 

 

          Note that during importing Microsoft.Web.Mvc.Html namespace in web.config, you also need to remove System.Web.Mvc.Html namespace because all HTML helpers are recreated in Microsoft.Web.Mvc.Html.HtmlHelperExtensions class. The benefit of using these new HTML helpers is that now these helpers will only allow legal attributes of an HTML element.

 

    AjaxOnly Action Method Selector:

 

          Action method selector allows you to select or ignore an action method under certain conditions. Sometimes, you need to only allow an action to execute if the request is an ajax request. Using ASP.NET MVC 3 Futures, you can decorate an action method with AjaxOnly attribute to meet this behaviour. Here is some code that shows you how to use this feature, 

 

1[AjaxOnly]
2public ActionResult MyAjaxMethod()
3{
4    return Content("My Ajax Method Contents.");
5}

 

 

 

    Value Providers:

 

          ASP.NET MVC 3 includes value provider for Form, QueryString, Route, HttpFileCollection, ChildAction and Json. ASP.NET MVC 3 Futures has some more value providers. These value providers includes ServerVariables, Session, TempData and Cookie. These value providers allows you to access session, server variables, temp data and cookie via action method parameters. For seeing these value providers in action, first you need to register them in Application_Start method,

 

1ValueProviderFactories.Factories.Add(new ServerVariablesValueProviderFactory());
2ValueProviderFactories.Factories.Add(new SessionValueProviderFactory());
3ValueProviderFactories.Factories.Add(new TempDataValueProviderFactory());
4ValueProviderFactories.Factories.Add(new CookieValueProviderFactory());

 

          Next, you need to add a new controller with the following code,

 

01public class NewValueProvidersController : Controller
02{
03    public ActionResult Index(string HTTP_USER_AGENT, string Name, string SName, string FullName)
04    {
05        Session["Name"] = "Imran";
06        TempData["SName"] = "Baloch";
07        Response.Cookies.Add(new HttpCookie("FullName", "Imran Baloch"));
08        return Content("");
09    }
10}

 

          In the above code, you are accessing session, server variables, temp data and cookie via action method parameters.

 

    CookieTempDataProvider:

 

          TempData allows you to store data between the current request and the request in which it is read. By default, TempData is stored in the session, but you can store it in a custom data store. Using ASP.NET MVC 3 Futures, you can replace TempData’s underlying data store with cookie. Here is an example that shows you how to store TempData inside a cookie,

 

01public class CookieTempDataProviderController : Controller
02{
03    public ActionResult Index()
04    {
05        if (TempData["Test"] == null)
06            TempData["Test"] = "Not Null";
07        return Content("");
08    }
09 
10    protected override void Initialize(RequestContext requestContext)
11    {
12        base.Initialize(requestContext);
13        TempDataProvider = new CookieTempDataProvider(requestContext.HttpContext);
14    }
15}

 

 

    DynamicViewPage:

 

          There are times when you just need to pass a very simple model to your view. In these cases, you may not want to bother a new view model. Rather, you can create an anonymous object and pass this model to your view. DynamicViewPage class allows you to do that easily. Here is an example,

 

1public class DynamicViewPageController : Controller
2{
3    public ActionResult Index()
4    {
5        return View(new { FirstName="Imran", LastName="Baloch"});
6    }
7}

 

01<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Microsoft.Web.Mvc.DynamicViewPage" %>
02 
03<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
04    Index
05</asp:Content>
06 
07<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
08 
09    <h2>Index</h2>
10    <%: Model.FirstName %>
11    <%: Model.LastName %>
12    </asp:Content>

 

          Note that I am inheriting the view with Microsoft.Web.Mvc.DynamicViewPage class. This is necessary, otherwise you will get an RuntimeBinderException exception.

 

    MvcDiagnostics:

 

          ASP.NET MVC 3 Futures contains a web form page called MvcDiagnostics.aspx. This page shows you the information about your application environment(OS name, Framework version, etc) and information about ASP.NET MVC assembly, ASP.NET MVC Futures assembly and all assemblies loaded inside the current application domain. This page also shows you an error, if ASP.NET MVC and ASP.NET MVC Futures assemblies are incompatible. To use this, just drop the MvcDiagnostics.aspx file into your application root directory and then navigate to /MvcDiagnostics.aspx. For details, see Diagnosing ASP.NET MVC Problems

 

    SerializationExtensions:

 

          Many times you need to persist/share/keep data across requests. There are many ways to do this. One way is to serialize your data into a hidden form field. Later, when the browser posts the form back, you can retrieve your data by deserializing the incoming hidden form value. Let's see an example to clearly see how it works,

 

01namespace UsingFeaturesASPNETMVC3Futures.Controllers
02{
03    public class SerializationExtensionsController : Controller
04    {
05        public ActionResult Index()
06        {
07            ViewData["Industry"] = new Industry { Name = "Alex Solutions", Address="Karachi, Pakistan" };
08            return View(new Job { Title = "Software Engineer", Level = "Senior" });
09        }
10 
11        [HttpPost]
12        public ActionResult Index(Job job, [Deserialize] Industry industry)
13        {
14            return Index();
15        }
16    }
17}
18namespace UsingFeaturesASPNETMVC3Futures.Models
19{
20    public class Job
21    {
22        public string Title { get; set; }
23 
24        public string Level { get; set; }
25    }
26 
27    public class Industry
28    {
29        public string Name { get; set; }
30 
31        public string Address { get; set; }
32    }
33}

 

01@using Microsoft.Web.Mvc
02@using UsingFeaturesASPNETMVC3Futures.Models
03 
04@model UsingFeaturesASPNETMVC3Futures.Models.Job
05 
06@{
07    ViewBag.Title = "Index";
08}
09 
10<h2>Index</h2>
11 
12<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
13<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
14 
15@using (Html.BeginForm()) {
16    @Html.ValidationSummary(true)
17    <fieldset>
18        <legend>Job</legend>
19 
20        <div class="editor-label">
21            @Html.LabelFor(model => model.Title)
22        </div>
23        <div class="editor-field">
24            @Html.EditorFor(model => model.Title)
25            @Html.ValidationMessageFor(model => model.Title)
26        </div>
27 
28        <div class="editor-label">
29            @Html.LabelFor(model => model.Level)
30        </div>
31        <div class="editor-field">
32            @Html.EditorFor(model => model.Level)
33            @Html.ValidationMessageFor(model => model.Level)
34        </div>
35        @Html.Serialize("Industry",ViewData["Industry"] as Industry)
36        <p>
37            <input type="submit" value="Save" />
38        </p>
39    </fieldset>
40}
41 
42<div>
43    @Html.ActionLink("Back to List", "Index")
44</div>

 

 

    Action Results:

 

          In ASP.NET MVC, the return type of a controller action called action result. An action result is responsible for writing the response. Several types of action results are supported in ASP.NET MVC 3 including ViewResult, RedirectResult, ContentResult, etc. ASP.NET MVC 3 Futures includes some more action results. These action results include an action result that uses DataContractSerializer class to render an object to the XML format(DataContractXmlActionResult), an action result that uses DataContractJsonSerializer class to render an object to the JSON format(DataContractJsonActionResult), an action result that uses Atom 1.0 entry format to render a SyndicationItem(AtomEntryActionResult), an action result that uses Atom 1.0 feed format to render a SyndicationFeed(AtomFeedActionResult), an action result that uses ServiceDocument format to render a ServiceDocument(AtomServiceDocumentActionResult),  an action result that uses specified format to return the response(MultiFormatActionResult) and an action result for returning HTTP errors that result from performing operations on resources(ResourceErrorActionResult).  Here is an example that leverages these new action results,

 

001namespace UsingFeaturesASPNETMVC3Futures.Models
002{
003    [DataContract]
004    public class Person
005    {
006        [DataMember]
007        public string FirstName { get; set; }
008 
009        [DataMember]
010        public string LastName { get; set; }
011    }
012 
013}
014namespace UsingFeaturesASPNETMVC3Futures.Controllers
015{
016    public class NewActionResultsController : Controller
017    {
018        public ActionResult Index()
019        {
020            return View();
021        }
022 
023        public ActionResult AtomEntryActionResultAction()
024        {
025            var item = GetAtomEntry();
026            return new AtomEntryActionResult(item);
027        }
028 
029        public ActionResult AtomFeedActionResultAction()
030        {
031            var feed = GetAtomFeed();
032            return new AtomFeedActionResult(feed);
033        }
034 
035        public ActionResult AtomServiceDocumentActionResultAction()
036        {
037            var doc = GetAtomService();
038            return new AtomServiceDocumentActionResult(doc);
039        }
040 
041        public ActionResult DataContractJsonActionResultAction()
042        {
043            return new DataContractJsonActionResult(new Person(){ FirstName = "Imran", LastName = "Baloch" });
044        }
045 
046        public ActionResult DataContractXmlActionResultAction()
047        {
048            return new DataContractXmlActionResult(new Person() { FirstName = "Imran", LastName = "Baloch" });
049        }
050 
051        public ActionResult MultiFormatActionResultAction()
052        {
053            return new MultiFormatActionResult(new Person() { FirstName = "Imran", LastName = "Baloch" }, new ContentType("application/xml"));
054        }
055 
056        public ActionResult ResourceErrorActionResultAction()
057        {
058            return new ResourceErrorActionResult(new HttpException(400,""),new ContentType("text/html"));
059        }
060 
061        #region Private Methods
062 
063        private static SyndicationItem GetAtomEntry()
064        {
066            SyndicationItem item = new SyndicationItem("My Item", "This is some content", new Uri("http://SomeServer/MyItem"), "Item ID", DateTime.Now);
067            item.Authors.Add(new SyndicationPerson("jesper@contoso.com", "Jesper Aaberg", "http://contoso/jesper"));
068            item.Categories.Add(new SyndicationCategory("Category One"));
069            item.Contributors.Add(new SyndicationPerson("lene@contoso.com", "Lene Aaling", "http://contoso/lene"));
070            item.Copyright = new TextSyndicationContent("Copyright 2007");
071            item.Links.Add(new SyndicationLink(new Uri("http://OtherServer/Item"), "alternate", "Alternate Link", "text/html", 1000));
072            item.PublishDate = new DateTime(2007, 2, 23);
073            item.Summary = new TextSyndicationContent("this is a summary for my item");
074            XmlQualifiedName xqName = new XmlQualifiedName("itemAttrib", "http://FeedServer/tags");
075            item.AttributeExtensions.Add(xqName, "ItemAttribValue");
076            return item;
077        }
078 
079        private static SyndicationFeed GetAtomFeed()
080        {
082            var item = GetAtomEntry();
083            SyndicationFeed feed = new SyndicationFeed();
084            Collection<SyndicationItem> items = new Collection<SyndicationItem>();
085            items.Add(item);
086            feed.Items = items;
087            return feed;
088        }
089 
090        private static ServiceDocument GetAtomService()
091        {
092            //Code copied from, http://msdn.microsoft.com/en-us/magazine/dd569753.aspx
093            ServiceDocument doc = new ServiceDocument();
094            doc.BaseUri = new Uri("http://localhost");
095            List<ResourceCollectionInfo> resources = new List<ResourceCollectionInfo>();
096            ResourceCollectionInfo mainBlog = new ResourceCollectionInfo("MSDNMagazine", new Uri("feed", UriKind.Relative));
097            mainBlog.Accepts.Add("application/atom+xml;type=entry");
098            resources.Add(mainBlog);
099            ResourceCollectionInfo mainPictures = new ResourceCollectionInfo("Pictures", new Uri("pictures", UriKind.Relative));
100            mainPictures.Accepts.Add("image/png");
101            mainPictures.Accepts.Add("image/jpeg");
102            mainPictures.Accepts.Add("image/gif");
103            resources.Add(mainPictures);
104            Workspace main = new Workspace("Main", resources);
105            doc.Workspaces.Add(main);
106            return doc;
107        }
108 
109        #endregion
110    }
111}

  

    Action Filters:

 

          ASP.NET MVC allows you to interfere in the execution pipeline of an action method through Action Filters. This means that you can do something before and after the action method executes. ASP.NET MVC 3 includes ChildActionOnly, OutputCache, HandleError, Authorize, and several other action filters. ASP.NET MVC 3 Futures contains an action filter for setting the content type of the response(ContentType), an action filter that supports multiple formats(HTML, XML, JSON etc), HTTP method based dispatch and HTTP error handling(WebApiEnabled) and an action filter that copy the action method parameters to AsyncManager.Parameters(CopyAsyncParameters). Here is an example that shows you how you can use these new action filters,     

 

01namespace UsingFeaturesASPNETMVC3Futures.Models
02{
03    public class Ground
04    {
05        public string Name { get; set; }
06 
07        public int Width { get; set; }
08 
09        public int Height { get; set; }
10    }
11}
12namespace UsingFeaturesASPNETMVC3Futures.Controllers
13{
14    public class NewActionFiltersController : AsyncController
15    {
16        public ActionResult Index()
17        {
18            return View();
19        }
20 
21        [CopyAsyncParameters]
22        public void CopyAsyncParametersAsync(string name)
23        {
24            // Here, name = AsyncManager.Parameters["name"]
25        }
26 
27        public ActionResult CopyAsyncParametersCompleted(string name)
28        {
29            return Content("Plain");// Without CopyAsyncParameters, name will be null
30        }
31 
32        [WebApiEnabled]
33        public ActionResult WebApiEnabledAction()
34        {
35            // With WebApiEnabled, this same action can return response in Html, Xml, Json format
36            // For Xml response, append ?format=Xml and for Json response, append ?format=Json
37            var ground = new Ground { Name = "Princeton Stadium", Width = 650, Height = 531 };
38            return View(ground);
39        }
40 
41        [ContentType("text/plain")]
42        public ActionResult ContentTypeAction()
43        {
44            return Content("Plain","text/html");// ContentType will override text/html
45        }
46    }
47}

 

          The CopyAsyncParameters attribute will synchronize the CopyAsyncParametersAsync action method parameters with AsyncManager.Parameters. The ContentType attribute allows you to set the content-type of the response. The framework will use the specified content-type, regardless what the action method returns. The WebApiEnabled attribute allows you to return the response of an action method in various format. WebApiEnabled was originally the part of Rest For ASP.NET MVC SDK. Now you can use it through ASP.NET MVC 3 Futures. In addition to WebApiEnabled, you can also use other features of Rest For ASP.NET MVC SDK like ResourceControllerFactory(as a base controller factory to make your application RESTful) and ResourceModelBinder(as a inner model binder with support for binding to other formats). This future assembly also contains some HTML, AJAX and URL helpers, which are useful for REST scenario. It also include RouteCollectionExtensions, which adds the routes to enable RESTful routing of requests to specified controller.    

   

    SkipBindingAttribute:

 

          The SkipBinding attribute allows you to skip the model binding process for certain action method parameters. This may be helpful for you if you are using some consistent action method parameters and these parameters are not interested in model binding process at all.        

 

01namespace UsingFeaturesASPNETMVC3Futures.Models
02{
03    public class Employee
04    {
05        public string Name { get; set; }
06 
07        public string Department { get; set; }
08    }
09}
10 
11namespace UsingFeaturesASPNETMVC3Futures.Controllers
12{
13    public class SkipBindingController : Controller
14    {
15        public ActionResult Index()
16        {
17            return View();
18        }
19 
20        [HttpPost]
21        public ActionResult Index([SkipBinding]Employee employee1, Employee employee2)
22        {
23            // Here, employee2 parameter will be model binded while employee1 not
24            return View();
25        }
26    }
27}

   

    Helpers and Extensions:

 

          ASP.NET MVC 3 Futures also contains some nice helpers and extensions. This includes,

          Script and Css HTML helpers make it easy for you to include css and script files in your view,

 

1@Html.Script("~/Scripts/jquery-1.4.4.js")
2@Html.Css("~/Content/Site.css")

 

          Name Extensions allows you to get the Id and Name of an expression,     

 

1@Html.Id("Name")
2@Html.Name("Name")
3@Html.IdFor(m => m.Name)
4@Html.NameFor(m => m.Name)
5@Html.IdForModel()
6@Html.NameForModel()

 

          You can use ImageExtensions to easily render HTML img element. You can use MailToExtensions to create a mailto link. You can use ButtonsAndLinkExtensions to generate HTML button, submit button and submit image element,

 

1@Html.Image("~/loading.gif")
2@Html.Mailto("Imran Baloch","imran_ku07@yahoo.com")
3@Html.Button("btnOK","OK",HtmlButtonType.Button)
4@Html.SubmitButton("btnSubmit","Submit")
5@Html.SubmitImage("imgSubmit", "~/loading.gif")

 

          With RadioListExtensions, you can easily create a group of radio buttons. Here is an example of using RadioButtonList HTML helper,

 

01@{
02    var sports = new[] {
03                            new{ Name = "Cricket", ID = 1 },
04                            new{ Name = "FootBall", ID = 2 },
05                            new{ Name = "Hockey", ID = 3 },
06                            new{ Name = "Tennis", ID = 4 }
07                        }.ToList();
08    var selectList = new SelectList(sports, "ID", "Name", 3);
09    MvcHtmlString[] radioButtons = Html.RadioButtonList("Sport", selectList);
10     for (int i = 0; i < radioButtons.Length; i++) {
11         @(sports[i].Name+": ") @radioButtons[i]
12    }
13}

 

          ViewExtensions has a generic Html.RenderAction<T> overload, LinkExtensions contains some generic Html.ActionLink<T> overloads, FormExtensions contains some generic Html.BeginForm<T> overloads, ControllerExtensions contains some generic Html.RedirectToAction<T> overloads. These overloads lets you to use a strongly typed lambda expression to reference a target action. Here is an example which uses these strongly typed extensions, 

 

1@{
2    using (Html.BeginForm<NewActionFiltersController>(action => action.ContentTypeAction()))
3    {
4        Html.RenderAction<HelpersAndExtensionsController>(action => action.Temp());
5        <br />
6        var act = Html.ActionLink<NewActionFiltersController>(action => action.ContentTypeAction(), "ContentTypeAction");
7        @act
8    }
9}

 

1public ActionResult Index()
2{
3    return View();
4}
5public ActionResult TempAction()
6{
7    // This is the Strongly Typed RedirectToAction
8    return this.RedirectToAction(action => action.Index());
9}

 

          AsyncManagerExtensions contains a RegisterTask method which allows you to register tasks by passing the target Begin and End methods. These tasks are then automatically handles the synchronization. The code below will show you how to use this extension,

 

01public void AsynchronousActionAsync()
02{
03    GetWeatherAsync();
04    GetLatitudeAndLongitudeAsync();
05    GetNewsAsync();
06}
07 
08private void GetWeatherAsync()
09{
10    WebRequest webRequest = WebRequest.Create("http://www.google.com/ig/api?weather=Karachi");
11    AsyncManager.RegisterTask(callback => webRequest.BeginGetResponse(callback, null), ar =>
12    {
13        var webResponse = webRequest.EndGetResponse(ar);
14        StreamReader stream = new StreamReader(webResponse.GetResponseStream());
15        string xml = stream.ReadToEnd();
16        XDocument doc = XDocument.Parse(xml);
17        var current_conditions = doc.Descendants("weather").Descendants("current_conditions").First();
18        AsyncManager.Parameters["condition"] = current_conditions.Element("condition").Attribute("data").Value;
19        AsyncManager.Parameters["temp_f"] = current_conditions.Element("temp_f").Attribute("data").Value;
20        AsyncManager.Parameters["temp_c"] = current_conditions.Element("temp_c").Attribute("data").Value;
21        AsyncManager.Parameters["humidity"] = current_conditions.Element("humidity").Attribute("data").Value;
22        AsyncManager.OutstandingOperations.Decrement();
23    }
24    );
25}
26 
27private void GetLatitudeAndLongitudeAsync()
28{
29    WebRequest webRequest = WebRequest.Create("http://where.yahooapis.com/geocode?q=Karachi");
30    AsyncManager.RegisterTask(callback => webRequest.BeginGetResponse(callback, null), ar =>
31    {
32        var webResponse = webRequest.EndGetResponse(ar);
33        StreamReader stream = new StreamReader(webResponse.GetResponseStream());
34        string xml = stream.ReadToEnd();
35        XDocument doc = XDocument.Parse(xml);
36        var result1 = doc.Descendants("ResultSet").Descendants("Result").First();
37        AsyncManager.Parameters["latitude"] = result1.Element("latitude").Value;
38        AsyncManager.Parameters["longitude"] = result1.Element("longitude").Value;
39    }
40    );
41}
42 
43private void GetNewsAsync()
44{
46    AsyncManager.RegisterTask(callback => webRequest.BeginGetResponse(callback, null), ar =>
47    {
48        var webResponse = webRequest.EndGetResponse(ar);
49        StreamReader stream = new StreamReader(webResponse.GetResponseStream());
50        string xml = stream.ReadToEnd();
51        XDocument doc = XDocument.Parse(xml);
52        var result1 = doc.Descendants().First().Descendants().First();
53        AsyncManager.Parameters["NewsTitle"] = result1.Elements().First().Value;
54    }
55    );
56}
57 
58public ActionResult AsynchronousActionCompleted(string condition, string temp_f, string temp_c, string humidity, string latitude, string longitude, string NewsTitle)
59{
60    ViewData["condition"] = condition;
61    ViewData["temp_f"] = temp_f;
62    ViewData["temp_c"] = temp_c;
63    ViewData["humidity"] = humidity;
64    ViewData["latitude"] = latitude;
65    ViewData["longitude"] = longitude;
66    ViewData["NewsTitle"] = NewsTitle;
67    ViewData["Title"] = "Asynchronous Action";
68    return View();
69}

   

          The above code uses the same example presented at here with a small difference: now AsyncManager.RegisterTask method is used, so no need to use AsyncManager.OutstandingOperations.Increment(or Decrement) method and no need to synchronize your calls because now AsyncManager.RegisterTask method will do this for you.

 

           With AreaHelpers, you can get the area name of the current request. IEnumerableExtensions contains an AsSerializable<T> extension method which allows an IEnumerable<T> type to be serialized by DataContractSerilizer.  Here is an example of using this,

 

01@{
02    var persons = new List<Person> { new Person { FirstName = "Cricket" }, new Person { FirstName = "FootBall" } }.AsQueryable().AsSerializable();
03    // Without AsSerializable(), you will get an exception
04    XmlWriterSettings settings = new XmlWriterSettings();
05    DataContractSerializer dcs = new DataContractSerializer(persons.GetType());
06    var sWriter = new StringWriter();
07    using (XmlWriter writer = XmlWriter.Create(sWriter))
08    {
09        dcs.WriteObject(writer, persons);
10        writer.Flush();
11    }
12}
13@sWriter

 

           Note that, if I remove AsSerializable() method from the above code then you will get an exception.     

 

        Summary:

          ASP.NET MVC 3 Futures comes with a bunch of features that can make your application run faster, easier to develop, more productive and maintainable. In this article, I showed you most of the features of ASP.NET MVC 3 Futures. I also showed you how to use these features in your application. I am attaching a sample application. Hopefully you will enjoy this article too. 

 

8 Comments

  • Hello Imran,
    Nice post. Will these features be available in MVC 3 after in future, or we have to enable them manually?
    Just a small fix:

    // Here, employee2 parameter will be model binded while employee2 not

    Maybe the "employee1" object will be skipped.

  • @Vest,
    There is no guarantee that which and what features will become the part of core ASP.NET MVC.

    You are correct, this was a typo. Corrected now.

  • Very nice post! MVC Futures is one of those things I recommend to everyone doing MVC development. The lambda-based extensions alone are worth the price of admission. :-)

  • Hi Imran, I have one requirement on using a Modeldataproviders, I want to make a field visible/invisible. can you please help me on that. thanks

  • @ak_netchat,
    It is bext to ask these type of questions in stackoverflow.com or forums.asp.net/1146.aspx

  • I do not drop many remarks, however I read a few of the remarks here
    Using the Features of ASP.NET MVC 3 Futures - Imran Baloch's Blog
    .
    I actually do have 2 questions for you if it's okay. Is it only me or does it seem like a few of the comments look as if they are coming from brain dead folks? :-P And, if you are posting at additional online sites, I would like to keep up with anything fresh you have to post. Would you post a list of the complete urls of all your social pages like your Facebook page, twitter feed, or linkedin profile?

  • I seldom drop comments, however i did some searching and wound up here Using the Features of ASP.NET MVC 3 Futures - Imran Baloch's Blog.

    And I actually do have a couple of questions for you if it's allright. Could it be just me or does it seem like some of the comments look like they are coming from brain dead individuals? :-P And, if you are posting at other online sites, I'd like
    to keep up with everything new you have to post. Could you list of every one of all your
    social pages like your Facebook page, twitter feed, or linkedin profile?

  • Great goods from you, man. I have understand your stuff previous to
    and you are just too great. I really like what you've acquired here, really like what you are stating and the way in which you say it. You make it entertaining and you still care for to keep it smart. I can not wait to read far more from you. This is actually a terrific website.

Comments have been disabled for this content.