Building Hybrid Mobile App to Reinforce Your ASP.NET MVC Website

26 Apr 2016

Web developers often struggle to create a mobile app that is meant to enhance an existing ASP.NET MVC web project. As you all know, there are two basic ways to approach this need - you can build either a native or hybrid app. Native apps are platform specific and require understanding of specific technologies and programming languages. Hybrid apps are written in HTML/JS/CSS and executed by the platform’s native Web view. Therefore, they can be reused across multiple platforms. So, the development of hybrid apps is usually simpler and faster. However, there is no difference between hybrid and native apps for Xenarius, as it allows you to quickly create both of them.

This tutorial demonstrates how to build a hybrid app while using an existing ASP.NET MVC solution as a back-end. The TicketDesk issue tracking system is used as an example. TicketDesk relies on a SQL database that allows you to store data: tickets, contact details, etc. When you run the TicketDesk app, it automatically attaches a database file to SQL Server and the database runs in an application process.

In this tutorial, you will complete the TicketDesk web app with the OData service to enable data exchange between back-end and a future mobile app. You will then learn how to create a hybrid app with Xenarius. Specifically, the tutorial will provide details on how to configure connection to the service and how to create a Login screen.

There is TicketDesk’s fork for this tutorial. Download the solution files from this fork and follow our step-by-step instructions at your convenience.

Contents

Part 1. Configuring Back-End

In order to provide an appropriate counterpart for a mobile app, an ASP.NET MVC application needs to be complemented with:

  • the OData service that will provide data for a mobile app;
  • authorization using the Web API.

Step 1. Enable Sample Database Generation

To allow the TicketDesk application to connect to your database, go to TicketDesk.Web.Client > Web.config and specify the database there.

In this tutorial, a sample database will be used. The database will be automatically created when the service runs.

To specify this database, configure the connection string as follows:

<add name="TicketDesk" connectionString="data source=localhost;Initial Catalog=TicketDesk;Integrated Security=True" providerName="System.Data.SqlClient" />

Note: In the data source setting, specify the actual SQL server name.

To allow automatic generation of the database, change a value of the ticketdesk:DemoModeEnabled key to true.

<add key="ticketdesk:DemoModeEnabled" value="true" /> 

Now you can preview the TicketDesk web application. Click F5.

During the first run, click Create Database to create a sample database. Then, go to the Ticket Center tab to view a list of tickets. You will be prompt to log in to TicketDesk. Use the email address “admin@example.com” with password “123456”.

TicketDesk web app

Step 2. Introduce OData Service

At this step, you will create an OData service providing data for a future mobile app.

  1. Create an OData controller:

    1. In Solution Explorer, right-click the Controllers folder in the TicketDesk.Web.Client project and select Add > Controller.
    2. In the Add Scaffold dialog, select Web API 2 Odata v3 Controller with actions, using Entity Framework and click Add.
    3. In the Add Controller dialog, do the following:

      1. In the Model class dropdown, select Ticket (TicketDesk.Domain.Model).
      2. Enable the Use async controller actions option.
      3. In the Data context class dropdown, select TdDomainContext(TicketDesk.Domain).
      4. In the Controller Name field, specify ODataTicketsController. Click Add.
  2. After the OData controller has been scaffolded, you will see the readme.txt file in Visual Studio. It says that the Global.asax.cs file may require additional changes to enable the ASP.NET Web API. You will need to follow the steps from this file:

    1. Add the following namespace references:

       using System.Web.Http;
       using System.Web.Routing;
      
    2. If the code does not yet define the Application_Start method, add the following method:

       protected void Application_Start()
       {
       }
      
    3. Add the following lines to the beginning of the Application_Start method:

      GlobalConfiguration.Configure(WebApiConfig.Register);
      

      At the next step, you will modify this Register method.

  3. Go to TicketDesk.Web.Client > App_Start > WebApiConfig.cs and add the following namespace references to the class.

     using System.Web.Http.OData.Builder;
     using System.Web.Http.OData.Extensions;
     using TicketDesk.Domain.Model;
    

    Then, add the following code to the Register method. This code specifies which entity type metadata will be exposed by the service.

    Note that this will not make data values available. To make data available to consumers, the OData controller is used.

     ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
     builder.EntitySet<Ticket>("ODataTickets");
     builder.EntitySet<Project>("Projects"); 
     builder.EntitySet<TicketEvent>("TicketEvents"); 
     builder.EntitySet<TicketSubscriber>("TicketSubscribers"); 
     builder.EntitySet<TicketTag>("TicketTags"); 
     config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
    

    After that, you can manage tickets via the OData service: http://localhost:44373/OData/ODataTickets.

    OData Service

Step 3. Add Authorization Using Web API

If you log out the TicketDesk web application, you will still have access to tickets via the OData service, that doesn’t comply with security requirements. Therefore, authorization must be implemented.

The TicketDesk MVC project already includes the authorization functionality, but it doesn’t suit the case when the data is exposed via the OData service. So, you need to implement authorization using the Web API.

  1. Create a controller for authorization.

    In the Controllers folder, create an ApiAccountController class using the code provided below. This class generally mimics code from TicketDesk’s AccountController, but adapts it for use of authorization in a mobile application.

    using Microsoft.AspNet.Identity.Owin;
    using System.Threading.Tasks;
    using System.Web.Http;
    using TicketDesk.Domain;
    using TicketDesk.Localization.Controllers;
    using TicketDesk.Web.Client.Models;
    using TicketDesk.Web.Identity;
     
    namespace TicketDesk.Web.Client.Controllers
    {
        public class ApiAccountController : ApiController
        {
        	private TicketDeskUserManager UserManager { get; set; }
        	private TicketDeskSignInManager SignInManager { get; set; }
            private TdDomainContext DomainContext { get; set; }
     
            public ApiAccountController(
            	TicketDeskUserManager userManager,
            	TicketDeskSignInManager signInManager,
            	TdDomainContext domainContext) {
            	UserManager = userManager;
            	SignInManager = signInManager;
            	DomainContext = domainContext;
            }
     
            [AllowAnonymous]
            //[Route("Login")]
            public async Task<IHttpActionResult> Login(UserSignInViewModel model) {
            	if(!ModelState.IsValid) {
            		return BadRequest();
            	}
         
                var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, true);
                switch(result) {
                  case SignInStatus.Success:
                		return Ok();
                	case SignInStatus.LockedOut:
                		return BadRequest("Lockout");
                	default:
                		ModelState.AddModelError("", Strings.InvalidLoginAttempt);
                		return BadRequest();
                }
     		    }
        }
    }
    
  2. The TicketDesk MVC project uses a dependency resolver. Now you need to create a Web API resolver that will wrap the MVC resolver.

    In the WebApiConfig.cs file, add the following namespace reference.

     using System.Web.Http.Dependencies;
    

    Then, add the following code that wraps the TicketDesk’s dependency resolver.

     public class WebApiResolver : IDependencyResolver {
     	System.Web.Mvc.IDependencyResolver mvcResolver;
     	public WebApiResolver(System.Web.Mvc.IDependencyResolver mvcResolver) {
     		this.mvcResolver = mvcResolver;
     	}
     
     	public IDependencyScope BeginScope() {
     		return new WebApiResolverScope(mvcResolver);
     	}
     
         public void Dispose() {
     		// do nothing
         }
     
     	public object GetService(Type serviceType) {
     		return mvcResolver.GetService(serviceType);
     	}
         
     	public IEnumerable<object> GetServices(Type serviceType) {
     		return mvcResolver.GetServices(serviceType);
     	}
     }
    
    public class WebApiResolverScope : IDependencyScope {
     	System.Web.Mvc.IDependencyResolver mvcResolver;
     	public WebApiResolverScope(System.Web.Mvc.IDependencyResolver mvcResolver) {
     		this.mvcResolver = mvcResolver;
     	}
     
     	public void Dispose() {
     		// do nothing
     	}
     
     	public object GetService(Type serviceType) {
     		return mvcResolver.GetService(serviceType);
     	}
     
         public IEnumerable<object> GetServices(Type serviceType) {
     		return mvcResolver.GetServices(serviceType);
         }
     }	
    
  3. Add the Web API resolver to the global configuration.

    Go to App_Start > Startup.SimpleInjector.cs and add the following namespace reference:

    using System.Web.Http; 
    

    Then, replace the code of the RegisterStructureMap container with the following code.

    public Container RegisterStructureMap(IAppBuilder app){
    	var container = GetInitializedContainer(app);
     
        var resolver = new SimpleInjectorDependencyResolver(container);
        DependencyResolver.SetResolver(resolver);
        GlobalConfiguration.Configuration.DependencyResolver = new WebApiResolver(resolver);
     
        return container;
    }
    
  4. Go to Controllers > ODataTicketsController and protect the ODataTicketsController class with the [Authorize] attribute:

     [Authorize]
     public class ODataTicketsController : ODataController
     {
     ...
     }
    

    Now if you log out the TicketDesk web application and try to open http://localhost:44373/OData/ODataTickets, you will be directed to log in.

    Login Page

Step 4. Enable Cross-Origin Access for Web API

When you create a mobile application that uses the OData service in Xenarius, you will preview the application in Xenarius Simulator. To make the application work in the simulator, the service should support cross origin requests via CORS (Cross-Origin Resource Sharing). To enable CORS, follow the steps:

  1. Install Microsoft.AspNet.WebApi.Cors for the TicketDesk.Web.Client project via NuGet.

  2. Go to TicketDesk.Web.Client -> App_Start-> WebApiConfig.cs and add the following namespace reference to the class.

    using System.Web.Http.Cors; 
    

    Then add the following code to the Register method:

    var corsAttr = new EnableCorsAttribute(origins: "*", headers: "*", methods: "*");
    corsAttr.SupportsCredentials = true;
    config.EnableCors(corsAttr); 
    
  3. Enable CORS for the OData controller.

    Open the ODataTicketsController.cs file and add the following namespace reference to the class:

     using System.Web.Http.Cors; 
    

    Then, add the [EnableCors("*","*","*",SupportsCredentials =true)] attribute to the ODataTicketsController class.

     [Authorize]
     [EnableCors("*","*","*",SupportsCredentials =true)]
     public class ODataTicketsController : ODataController
     {
     ...
     }
    

As a result, you will get a service project similar to this sample service project.

Part 2. Creating a Mobile App with Xenarius

After the back-end is configured, you can develop a mobile version of TicketDesk with Xenarius. This is a sample Xenarius project that builds such a mobile application. You can download the sample project, import it to Xenarius and explore it. Before running the application, make sure the actual service URL is specified in two places:

  1. in the data provider settings
  2. in the On Click event handler for the Login button

To develop a similar application, follow these steps.

Step 1. Create Xenarius Project

Go to the Xenarius main menu, click Create Project and select Empty Project.

On the Application Options page, specify the application ID and title.

Step 2. Configure Data Connection

In the Data menu, select Create a new data provider and specify its properties:

  • Select the OData data provider type since the back-end you prepared earlier exposes data via the OData service.
  • Enter Tickets as the provider name.
  • Enter the OData service URL to be used in both development and production.
  • Specify TicketId as the Key Property as per the database schema.
  • Leave the Key Type set to Int32.
  • Choose the 3rd OData version.

Creating Data Provider

Step 3. Create Application Views

The application will consist of three views:

  • Tickets - shows a list of existing tickets.
  • Ticket Details - shows information about an individual ticket, allows creating/updating a ticket.
  • Login - allows you to log into TicketDesk using your user credentials.

The Tickets and Ticket Details views will be similar to the Incident and Incident Details views of the Getting Started application. So, to implement these views along with navigation between them and the create/update/delete functionality in the application, you can use the getting started instructions.

Tickets View Ticket Details View

If you run the application at this step, you will not have access to tickets, because you aren’t currently logged in TicketDesk. There’s no capability to log in from this mobile app. So, now you need to create a view that allows logging in the TicketDesk app.

Step 4. Create Login View

To create the Login view, follow the steps below.

  1. Create a new view and drag and drop two inputs and a button to it.

  2. Add two properties (login and password) to the view.

    View Properties

  3. Bind the inputs to these properties.

    Binding

  4. Create the On Click handler function for the Login button. Add operations to the function as it is shown in the image below.

    On Click Handler

    The On Click function will send the POST request to log in a user with the specified credentials. If the credentials are true, clicking the Log in button will navigate to the Tickets view. If the user credentials are not valid, the error message will be displayed.

    Two notes:

    1. In the Send request operation, you need to specify a url expression in single quotation marks.
    2. Make sure that the Send Cookies option is set to Yes.
  5. Specify the Login view as the default view in the Navigation section of the application options.

Default View

Step 5. Run Application

Run the application in Xenarius Simulator. In the Login view, log in to TicketDesk using the email address “admin@example.com” with password “123456”. After that, you will be able to manage tickets.

App Preview

Step 6. Deploy Application

To test the application on mobile devices or publish it in an application store, use the Deploy function. Click the Deploy button on the main toolbar, and select Hybrid/HTML5 App. Your browser will download a zip file with the application. Then, you can compile and package it using PhoneGap Build.