Tag Archives: Mobile Web browsers

HTML5, jQuery Mobile and ASP.NET MVC 4–Using ViewModel between the model and controller

You can download from Windows Store at http://apps.microsoft.com/webpdp/en-US/app/emergency-help-me/477b898a-6781-4b75-a439-44dee5904f14

To get started with the development, we have seen the post Introduction to HTML5 Development Using VS 2010, HTML5, jQuery Mobile and ASP.NET MVC 4.

In an enterprise application development scenario, we might need to aggregate some of the models/data sources and present it as a whole to the controller. For simplicity, let us take a case where we need to enter new student Name, Grade and the State as shown in Fig 1.

The Grades are A, B & C. But it might make much sense if we can show these grades as First Class, Second Class, Third Class instead of A,B & C in the UI. So in the UI, we need to show  First Class, Second Class, Third Class but while saving the data we need to save the corresponding values in the DB. Same holds for the state as well. When the user clicks on state dropdown selection icon, the states list pops up and displays all the states. When a state is selected, it is shown in the UI but when saved to the DB, the code names are saved like CA for California as shown in figure 2.

image

Fig 1: Form for entering new student information

image

Fig 2: When clicked on the State drop down list, the above screen pops up.

The Magic of ViewModel: ViewModels allow you to shape multiple entities from one or more data models or sources into a single object, optimized for consumption and rendering by the view. The below figure 3 illustrates the concept of a ViewModel:

image

Fig 3: StudentViewModel aggregating the different models and data sources and supplying the information to the view as a single entity.

The purpose of a ViewModel is for the view to have a single object to render, alleviating the need for UI logic code in the view that would otherwise be necessary. This means the only responsibility, or concern, of the view is to render that single ViewModel object, aiding in a cleaner separation of concerns (SoC). Concerns are distinct aspects of the application that have a particular purpose (i.e., concern), and keeping these aspects apart means your application is more organized, and the code more focused. Putting data manipulation code in its own location away from the view and controller, enforces SoC. Using ViewModels in MVC  leads to more easily maintainable and testable code.

Let us create our data sources. The first one is the grade and the code is as follows. The Grades class is a simple Dictionary object containing two type parameters of type string. The class also contains the definitions for all the members in the Dictionary (i.e., the grades data). The only property in the Grades class is the GradeSelectList, which is an object that Html Helpers use with to render an HTML <select> element that displays a listing of grades. The type Dictionary<string, string> in the GradeSelectList property maps to the grades abbreviation then grade name, respectively.

public class Grades
{
    public static SelectList GradeSelectList
    {
        get
        {
            return new SelectList(GradeDictionary, "Value", "Key");
        }

    }

    public static readonly IDictionary<string, string>
            GradeDictionary = new Dictionary<string, string>
            {
              {"Choose…",""}
            , { "First Class", "A" }
            , { "Second Class", "B" }
            , { "Third Class", "c" }
            };
}

 

The same login for the states. The code for StatesDictionary is as follows.

public class StatesDictionary
{
    public static SelectList StateSelectList
    {
        get { return new SelectList(StateDictionary, "Value", "Key"); }
    }

    public static readonly IDictionary<string, string>
        StateDictionary = new Dictionary<string, string> {
      {"Choose…",""}
    , { "Alabama", "AL" }
    , { "Alaska", "AK" }
    , { "Arizona", "AZ" }
    , { "Arkansas", "AR" }
    , { "California", "CA" }
    , { "Colorado", "CO" }
    , { "Connecticut", "CT" }
    , { "Delaware", "DE" }
    , { "District of Columbia", "DC" }
    , { "Florida", "FL" }
    , { "Georgia", "GA" }
    , { "Hawaii", "HI" }
    , { "Idaho", "ID" }
    , { "Illinois", "IL" }
    , { "Indiana", "IN" }
    , { "Iowa", "IA" }
    , { "Kansas", "KS" }
    , { "Kentucky", "KY" }
    , { "Louisiana", "LA" }
    , { "Maine", "ME" }
    , { "Maryland", "MD" }
    , { "Massachusetts", "MA" }
    , { "Michigan", "MI" }
    , { "Minnesota", "MN" }
    , { "Mississippi", "MS" }
    , { "Missouri", "MO" }
    , { "Montana", "MT" }
    , { "Nebraska", "NE" }
    , { "Nevada", "NV" }
    , { "New Hampshire", "NH" }
    , { "New Jersey", "NJ" }
    , { "New Mexico", "NM" }
    , { "New York", "NY" }
    , { "North Carolina", "NC" }
    , { "North Dakota", "ND" }
    , { "Ohio", "OH" }
    , { "Oklahoma", "OK" }
    , { "Oregon", "OR" }
    , { "Pennsylvania", "PA" }
    , { "Rhode Island", "RI" }
    , { "South Carolina", "SC" }
    , { "South Dakota", "SD" }
    , { "Tennessee", "TN" }
    , { "Texas", "TX" }
    , { "Utah", "UT" }
    , { "Vermont", "VT" }
    , { "Virginia", "VA" }
    , { "Washington", "WA" }
    , { "West Virginia", "WV" }
    , { "Wisconsin", "WI" }
    , { "Wyoming", "WY" }    
    // more states
    };
}

Data that lives in small lists and infrequently changes, like the Grades, StatesDictionary class, exists in all types of applications.

Creating Model:

Now we need a model that collects the student’s name, the grade, and the state he is from as shown in Figure 1.  The StudentModels class definition captures these features in simple data structure. Let us now create a StudentModels class as shown below. Create a file StudentModels.cs under Models folder and add the following code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace TagStatus.Models
{
    public class StudentModels
    {
        [Display(Name = "Student Name here")]
        [Required()]
        public string StudentName { get; set; }
        public string Grade { get; set; }
        public string State { get; set; }
    }
}

 

Creating ViewModel:

Because of the data coming from different sources that needs to be displayed in the view, coding and maintenance will be easier if you use a ViewModel. ViewModels are a combination of one or more types that together shape data that goes to the view for consumption and rendering. A ViewModel is just a class. To get started, create a new folder named ViewModels and add a new code file StudentViewModel.cs to it. To create the StudentViewModel ViewModel, add the StudentModels, Grades  and StatesDictionary types as properties to form one StudentViewModel class. In the source code below, the StudentViewModel class contains the newly defined properties.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using TagStatus.Models;

namespace TagStatus.ViewModels
{
    public class StudentViewModel
    {
        public StudentModels Student { get; set; }
        public Grades Grades { get; set; }
        public StatesDictionary States { get; set; }

        public StudentViewModel(StudentModels student)
        {
            Student = student;
            Grades = new Grades();
            States = new StatesDictionary();
        }

        public StudentViewModel()
        {
            Student = new StudentModels(); ;
            Grades = new Grades();
            States = new StatesDictionary();
        }
    }
}

 

Creating Controller:

After creating the ViewModel, the next steps are to instantiate it in a controller and return it to the view. I am doing R & D on this new MVC4 and so you will see some messy code.

The following code  creates a Controller Passing the ViewModel to the View and the code of interest for us is public ActionResult StudentInfo() and this gets executed while the application is firing up.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using TagStatus.Models;
using TagStatus.ViewModels;

namespace TagStatus.Controllers
{
    public class StudentController : Controller
    {
        //public string StudentName { get; set; }
        //public int Grade { get; set; }

        //
        // GET: /Student/

        public ActionResult Index()
        {
            StudentModels stdm = new StudentModels();
            StudentViewModel stdvm = new StudentViewModel(stdm);
            return View(stdvm);
        }

        //[AllowAnonymous]
        //public ActionResult StudentInfo()
        //{
        //    return View();
        //}

        [AllowAnonymous]
        [HttpPost]
        public ActionResult StudentInfo(StudentModels model)
        {
            if (ModelState.IsValid)
            {
                model.StudentName = model.State;
            }

            return View(model);
        }

        [AllowAnonymous]
        public ActionResult StudentInfo()
        {
            StudentViewModel model = new StudentViewModel();

                //model.StudentName = model.State;

            return View(model);
        }

    }
}

Creating HTML5 Mobile Forms in ASP.NET MVC 4 Views:

In Visual Studio 2010, Right click on project and  Add New Item command to create StudentInfo.cshtml, the view that will host your HTML5 form. Inside the view, various ASP.NET MVC 4 Html Helpers present components of the StudentViewModel by rendering HTML elements that best fit the data types they map to in the ViewModel. For example, Grade renders as an HTML drop-down list so that the user can easily select an item rather than manually enter it.

The code for StudentInfo.cshtml is as follows.

@model TagStatus.ViewModels.StudentViewModel;
@{
    ViewBag.Title = "Student Info";
}

<h2> New Student </h2>
@using (Html.BeginForm("Results","Home"))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Enter Student Information!</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Student.StudentName)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(Model => Model.Student.StudentName)
           @Html.ValidationMessageFor(Model => Model.Student.StudentName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Student.Grade)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(Model => Model.Student.Grade, Grades.GradeSelectList)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Student.State)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(Model => Model.Student.State, StatesDictionary.StateSelectList)
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

 

Download the source code from here and make the following change in the Global.asax file.

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

If you don’t go after what you want, you’ll never have it. If you don’t ask, the answer is always no. If you don’t step forward, you’re always in the same place.Nora Roberts

Introduction to HTML5 Development Using VS 2010, HTML5, jQuery Mobile and ASP.NET MVC 4

You can download from Windows Store at http://apps.microsoft.com/webpdp/en-US/app/emergency-help-me/477b898a-6781-4b75-a439-44dee5904f14

Mobile apps and HTML5 are two of the hottest technologies right now, and there’s plenty of overlap. Web apps run in mobile browsers and can also be re-packaged as native apps on the various mobile platforms. Browser adoption for HTML5 features is accelerating rapidly. Many of the modern browsers (Chrome, Safari, Firefox, and Opera) already support between 75% and 90% of the feature set and this number is increasing daily. With the wide range of platforms to support, combined with the sheer power of mobile browsers, HTML5 is the “Write once, run anywhere” (WORA)solution. Modern mobile devices consist of powerful browsers that support many new HTML5 capabilities, CSS3 and advanced JavaScript. To see what features your browser supports, check out sites like html5test.com, caniuse.com. jquerymobile.com and html5please.com

In this post we will learn how to create a mobile Web applications that take advantage of HTML5, jQuery Mobile and ASP.NET MVC 4, you can effectively target multiple platforms with a single code base. Any browser, including mobile Web browsers, can render the HTML pages created with these technologies. You’ll still need to consider dealing with different browsers, but overall, Web applications are much easier to develop and maintain than multiple native applications in different languages.

Lets get started with the latest tools for Microsoft Web development: HTML5, jQuery Mobile and ASP.NET MVC 4
 

Tools Needed for development (download and install):

See the Windows Phone getting started guide at http://create.msdn.com/en-us/home/getting_started. After we develop in MVC4, use the Windows Phone Emulator to test the page with something closer to an actual mobile device.

JQuery Mobile is also part of the MVC 4 Mobile Web Application template in Visual Studio 2010. With the MVC 4 template, you can develop mobile Web sites with a consistent look and feel by using prebuilt themes, navigation and widgets. Additional features include built-in accessibility, touch and an API, so you can easily customize your applications. Click here to see a comprehensive list of supported platforms.

Creating a HTML5 application:

To create a new application, Open VS 2010 , select New from the File menu, and then  New Project.  The New Project dialog box pops up as shown in figure 1. Name it as tag status.

The application displays the information related to a bar code tag. So we need a place holder to enter barcode tag number and a button to retrieve the description through the API. And then another read only textblock to display its description.

image

Fig 1: New Project dialog box – ASP.NET MVC4 Web application

The Mobile Application template contains the necessary jQuery and jQuery Mobile scripts as well as other necessary markup, such as semantic elements and the data-* attributes.

Figure 2 shows the application in windows phone 7. As you can see, we have a textbox so that the user can enter a barcode tag number and click on submit. Then we display the description in the textbox below the button. For simplicity, when the user clicks on the submit button, I am displaying the information entered by the user in tag number as the description.

imageimage

Fig 2: HTML5 mobile application

Adding Model Class:
  • In the Solution Explorer, expand the solution files
  • Right Click on Models –> Add –> Class. Name it as TagModels (TagModels.cs) and add the following code. Regardless of whether the target is mobile or desktop, HTML5 form elements map to a property of an entity in a model. Because models expose varied data and data types, their representation in the user interface requires varied visual elements, such as text boxes, drop-down lists, check boxes and buttons.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace TagStatus.Models
{
    public class TagModel
    {
        [Display(Name = “Enter Tag Number”)]
        [Required(ErrorMessage = “The Tag Number field is required.”)]
        public string Name { get; set; }
        public string Description { get; set; }
    }
}

 

In the above model code, you can see the Data Annotations Display and Required. Before the form submission process sends the HTTP Request to the server, client-side validation needs to happen. Annotating the data model accomplishes this task nicely. In addition to validation, data annotations provide a way for the Html.Label and Html.LabelFor helpers to produce customized property labels. The figure 3 shows the data annotation after the search button is clicked without entering data in the Windows Phone 7 Emulator.

image

Fig 3: Data Annotations in HTML5

Adding controller Class:

The idea here is that the controller must pass the model to the view for rendering.

  • In the Solution Explorer, expand the solution files
  • Right Click on Controllers–> Add –> Controller. Name it as TagController(TagController.cs) and add the following code. The names are very important. You can see that the class is derived from Controller class. Here we added two methods for Lookup() action.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TagStatus.Models;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Http;
using System.Dynamic;
using System.Data;
using System.Json;

namespace TagStatus.Controllers
{
    
    public class TagController : Controller
    {
        //
        // GET: /Tag/

        public ActionResult Index()
        {
            return View();
        }

        [AllowAnonymous]
        public ActionResult Lookup()
        {
            return View();
        }

        [AllowAnonymous]
        [HttpPost]
        public ActionResult Lookup(TagModel model)
        {
            if (ModelState.IsValid)
            {
            //    //string url = “https://myapicom/svc1/v2/tags?project=usax&format=JSON&#8221;;

                model.Description = model.Name;

            //   /* CallApi apiPOItems = new CallApi()
            //    {
            //        ApiUrl = ConfigurationManager.AppSettings[“Url_PO_LineItems”].Replace(“{PO_NUMBER}”, PONumber),
            //        Format = “xml”,
            //        PageSize = intPageSize.ToString(),
            //        Page = mintCurPage.ToString(),
            //        Filter = getFilterString(),
            //        OrderBy = ((hdnPOLNSortOrder.Value != “”) ? hdnPOLNSortOrder.Value : “poln_lineno asc”)
            //    };

            //    ds = apiPOItems.RetrieveData(ref strErrorMsg, ref intRecordCount);*/

            //    string strErrorMsg = “”;
            //    int intRecordCount = -1;
            //    DataSet ds;

            //    CallApi apiPOItems = new CallApi()
            //    {
                    
            //        //ApiUrl = “https://myapicom/svc1/v2/tags/00-RIE-FF-03?project=usax&#8221;,
            //        ApiUrl = sApiUrl,
            //       // Format = “xml”,
            //        Format = “”,
            //        PageSize = “10”,
            //        Page = “1”,
            //        Filter = “”,
            //        OrderBy = “”
            //    };

            //    CallApi.ConnectCallComplete = true;

            //   // ds = apiPOItems.RetrieveData(ref strErrorMsg, ref intRecordCount);
            //    string strjsonres = apiPOItems.RetrieveJSON();
            //    JsonObject jsonObject = (JsonObject)JsonValue.Parse(strjsonres);

            //    var strvar = JsonValue.Parse(strjsonres);

            //    var t1 = strvar[“tags”];
            //    var t2 = t1[“tags”];

            //    var t3 = t2[“tags_delivery_status”];

            //    String strdeliverystatus = t3.ToString();
            //    strdeliverystatus = strdeliverystatus.Replace(“\””,””);
            //    strdeliverystatus = strdeliverystatus.Replace(“\\u000a”, “<bR>”);
            //    strdeliverystatus = “<b>” + strdeliverystatus + “<b>”;

            //   // var v = jsonObject[“tags”];
            //   //// JsonArray items = (JsonArray)jsonObject[“tags”];
            //   // var vv = v[1];
            //   // JsonValue jsval;
            //   // bool b = jsonObject.TryGetValue(“tags_delivery_status”, out jsval);

            //    if (strErrorMsg != “”)
            //    {
            //        // There was an ERROR
            //    }

            //    //model.Description = ds.Tables[2].Rows[0][“tags_description”].ToString();
               

            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

    }
}

 
Adding View:
  • In the Solution Explorer, expand the solution files
  • Right Click on Views–> Add –> New Folder. Name it as Tag as shown in fig 4.
  • Right Click on Tag Folder –>Add  New Item to create Lookup.cshtml as shown in figure 5.

image

Fig 4: Solution Explorer folder layout

image

Fig 5: Selecting a new View

  • Add the following code to the Lookup.cshtml
@model TagStatus.Models.TagModel

@{
    ViewBag.Title = “Tag Status Application”;
}

<h2>Tag Status Lookup</h2>

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)    
    //style=”background-color: #C0C0C0″
    
    <fieldset>
        <legend></legend>
        <div class=”editor-label”>
            @Html.LabelFor(m => m.Name)
        </div>

      <div class=”editor-field”>
            @Html.TextBoxFor(Model => Model.Name)
           @Html.ValidationMessageFor(Model => Model.Name)
        </div>
        <p>
            <input type=”submit” value=”Search” />
        </p>
     <div class=”editor-label”>
            @Html.DisplayTextFor(m => m.Description)
        </div>
    </fieldset>
}

@*@using (Html.BeginForm())
{
    //style=”background-color: #C0C0C0″
        
    <p>Enter tag number to get tag status:</p>
    @Html.TextBoxFor(m => m.Name)
           
    <input type=”submit” value=”Search” />
    
    @Html.DisplayTextFor(m => m.Description)

   
}
*@

 

The view is the one that will host your HTML5 form. ASP.NET MVC 4 favors a development technique named convention over configuration, and the convention is to match the name of the action method (Lookup) in the controller with the name of the view, that is, Lookup.cshtml.

Inside the view, various ASP.NET MVC 4 Html Helpers present components of the ViewModel by rendering HTML elements that best fit the data types they map to in the ViewModel.

Final step (Global.asax):

To get the Tag status page displayed when the application is run, change the RegisterRoute and add the Tag Controller and the action Lookup as shown below in Global.asax file.

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

            routes.MapHttpRoute(
                name: “DefaultApi”,
                routeTemplate: “api/{controller}/{id}”,
                defaults: new { id = RouteParameter.Optional }
            );

            routes.MapRoute(
                name: “Default”,
                url: “{controller}/{action}/{id}”,
               defaults: new { controller = “Tag”, action = “Lookup”, id = UrlParameter.Optional }
                //defaults: new { controller = “Student”, action = “StudentInfo”, id = UrlParameter.Optional }
                //defaults: new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }
            );
        }

With the Model, View and Controller in place, let us execute the project.

Testing the HTML Form on the Windows Phone 7 Emulator:

Running the app from Visual Studio through browser is the easiest way to test the form, but the look and feel doesn’t behave in a very mobile-like way. For viewing the output and testing the form, the Windows Phone 7 Emulator works perfectly.

The HTML5 form displays in the Windows Phone 7 Emulator, as shown in figure 2 . You can enter a tag number and submit the form. Submitting the form directs the browser to send the form information to the Tag controller because of the call to the Html Helper, Html.BeginForm( ). The BeginForm method directs the HTTP request to the TagController controller and then runs the Lookup action method when the submit button is pressed.

Once the user taps the submit button on the phone—and assuming the form passes validation—an HTTP POST Request is initiated and the data travels to the controller and to the Lookup action method. The controller code that lives in the TagController and processes the data that the HTTP Request sends. Because of the power of ASP.NET MVC 4 model binding, you can access the HTML form values with the same strongly typed object used to create the form – your Model.

You can immediately examine the modifications the jQuery Mobile library made by taking the following steps:

  1. Launch a Web page from within Visual Studio (F5/Ctrl).
  2. Open the browser’s developer tools to expose the runtime source (F12 in most browsers).
  3. Use the View Source command to expose the originally rendered source.

You can see the html returned to the client is different from our source.

Software development is shifting toward the mobile space. Businesses want to carve their niche in the mobile marketplace with native mobile applications and mobile Web sites – the two types of applications available for mobile devices. Creating native applications with native code means developing separate software that targets each platform of interest (e.g., one XAML app for Windows Phone 7 and one Objective-C app for iOS). Maintaining and supporting multiple code bases is challenging, in part because most software developer teams don’t have the resources to do so, especially across a large number of customers. Independent contractors often have to focus on only one or two platforms, limiting their prospects.

Download source code here.

“The future belongs to those who see possibilities before they become obvious.” — John Scully