7/28/18

ASP.NET MVC Apps on Virtual Directory with IIS Express

On previous articles, we learned how to deploy multiple ASP.NET MVC Apps on the same Azure Web App by using virtual applications.  We also learned that for some cases when more than one application defines the same routes, this may lead to an ambiguous routing request if not configured properly.

Previous Articles





In this article, we learn how to configure our development environment with a virtual directory and have a second app run on the same process which should simulate the environment on Azure.

IIS Express Configuration

Visual Studio Solutions contain a .vs folder with solution configuration information. In that folder, we can find a config folder with an applicationhost.config file.  This is the file that enables us to configure IIS Express when running apps from Visual Studio.

When we open the file, we should look for the sites node (xml node). This is where the sites/apps definitions can be found for a solution. In the case of a solution with two ASP.NET projects, we can find a setting similar to this:


<site name="ozkary.azure.vdir.main" id="2">

    <application path="/" applicationPool="ozkary.azure.vldir.main AppPool">

        <virtualDirectory path="/" physicalPath="d:\repos\ozkary.vdir\main" />

    </application>

    <bindings>

        <binding protocol="http" bindingInformation="*:61823:localhost" />

    </bindings>
</site>

<site name="ozkary.azure.vdir.admin" id="3">

    <application path="/" applicationPool="ozkary.azure.vdir.admin AppPool">

        <virtualDirectory path="/" physicalPath="d:\repos\ozkary.vdir\admin" />

    </application>

    <bindings>

        <binding protocol="http" bindingInformation="*:62029:localhost" />

    </bindings>
</site>



In the settings, there are two sites, main and admin.  Both of those sites run from a different local folder and a different port. If we translate this to an Azure deployment, we will need to deploy to two different web apps.

Our goal is to change to using only one app, and deploy the admin site as a virtual app under the main site.  To do this using IIS Express, we need to configure the main app setting to read the following:


<site name="ozkary.azure.vdir.main" id="2">

<application path="/" applicationPool="Clr4IntegratedAppPool">
           <virtualDirectory path="/"    physicalPath="d:\repos\ozkary.vdir\main" />

</application>

<application path="/admin" applicationPool="Clr4IntegratedAppPool">
          <virtualDirectory path="/" physicalPath="d:\repos\ozkary.vdir\admin" />

</application>

<bindings>
        <binding protocol="http" bindingInformation="*:61823:localhost" />

</bindings>

</site>


To review, we just add another application setting under the same site configuration. We are careful in setting the path information otherwise this can lead to errors. We set the new application node path attribute to the virtual directory name (admin). We then set the virtualDirectory node attribute path to the root of the second project which should have a different physical path.  This essentially is the same as if we would do this on an IIS Server.

Validate the configuration:

To validate that our configuration is working properly, we can take a look at the process that IIS Express is creating for us. We first take a snapshot of the process prior to making the virtual directory entry. If we run the projects, we would see that both projects are running with a different process ids,  PID. This is shown on this image below which is taken from the IIS Express admin app which is available from the system tray.


We can then stop the applications and add the additional application node under the main site.  We are now ready to lunch the applications again and take another snapshot.  We should now see that both applications are running under the same process id PID 25860.




After validating this locally, you can deploy to Azure and validate that this is working with no conflicts. To learn how to deploy to Azure using a virtual directory, review the article below:


  


Hope this is helpful and thanks for reading.

Originally published by ozkary.com

7/14/18

ASP.NET MVC Routing Error Multiple Controller Types on Azure Virtual Directory

In a previous article, I wrote about hosting an ASP.NET MVC app on a virtual directory on Azure.  You can find the article in the link below.  The main goal of that article was to show how to hosts other sites within the same Azure Web app.



There are cases when the multiple sites have similar routes and controllers, and the application find this ambiguous and does not know how to handle a request showing this error:



[InvalidOperationException: Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.

The request for 'Home' has found the following matching controllers:
Admin.Controllers.HomeController
Main.Controllers.HomeController]
               
This error is somewhat odd because a deployment to a virtual directory should isolate the routes per application and there should not be this ambiguity.

Review Deployment and Configuration

When facing such error, we need to check the following possible problems:

1) When doing the deployment, we need to make sure the destination URL includes the virtual directory folder
For example:   www.mysite.com/admin    where admin is the virtual directory folder.

2) Make sure the virtual directory root folder is not the same as the main site
This is a common mistake. When doing the configuration for a virtual directory we must make sure to set the correct physical path as shown next:


The image shows how the main application and virtual path use different physical paths. If both are set to the same physical path, then the routes will be processed from both apps with the same route but different controller types which causes the ambiguity.

Before doing the deployment to Azure make sure to test this configuration on your development environment. For those using Visual Studio with IIS Express, you may find this article useful:
I hope this is helpful.

Originally published by ozkary.com

6/23/18

Xamarin Android WebView Authentication

The WebView browser component is commonly used to render web content within a native application layout. When the content is secured, it is required for the app to authenticate with the Web server first.  When using the WebView component, we can leverage the component events (HTTP pipeline) to detect a challenge-response authentication event from the server and automatically login our app.

Challenge Response Security



The challenge-response interaction is a security protocol (HTTP 401) event in which a server challenges the identity of a client, and the browser responds with the security credentials required to access the content. If the required credentials are not validated, the content is forbidden to the app. We can leverage this interaction to send the impersonating identity to the server by extending the WebViewClient class and overriding the authentication event. Let’s take a look.

Extending the WebViewClient Class

In order to write a handler for the challenge-response event, we need to extend the WebViewClient class. We start by implementing a constructor that can take the credential information. This enables the activity that instantiates our class to manage the credential information and just pass it to our class during the class instantiation.


internal class AuthWebViewClient : WebViewClient
{
    public string Username { get; }
    public string Password { get; }
    private int LoginCount = 0;
    
    /// <summary>
    /// gets the user credentials for the impersonation process
    /// </summary>
    /// <param name="username"></param>
    /// <param name="password"></param>
    public AuthWebViewClient(string username, string password)
    {
        Username = username;
        Password = password;          
    }
    
    /// <summary>
    /// handles the authentication with the website.
    /// </summary>
    /// <param name="view"></param>
    /// <param name="handler"></param>
    /// <param name="host"></param>
    /// <param name="realm"></param>
    /// <remarks>
    /// </remarks>
    public override void OnReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, string host, string realm)
    {
        try
        {
            if (LoginCount < 3)
            {
                LoginCount++;
                handler.Proceed(Username, Password);
            }
            else
            {
                LoginCount = 0;
                handler.Cancel();
            }
        }
        catch (Exception ex)
        {
            Toast.MakeText(Application.Context, ex.Message, ToastLength.Long).Show();
        }
    }      
}


Handling the Authentication

When we extend the WebViewClient class, we can override some of the class events. For the authentication pipeline, we override the OnReceivedHttpAuthRequest event which provides a reference to the HttpAuthHandler object. This object provides the Proceed method which we use to send the login credentials to the server.

One important area to note here is that if there is a problem with the credentials that we send to the server, the HTTP 401 event will continue to be sent back from the server. This can create a loop between the browser and server. To prevent this, we track the number of attempts, and cancel the authentication when the limit is met. This is done by using the Cancel method on the HttpAuthHandler object.

Please note that this simple approach to pass the username and password information from the browser to the server. There are still other securities areas to be concerned with like encrypting the communication channel to protect the security credentials from unwanted traces.


Thanks for reading.

Originally published by ozkary.com

6/2/18

Xamarin Android Class Not Found Exception

The Class Not Found Exception is commonly raised when the class loader tries to find an activity or a broadcast receiver class listed on the app manifest, but it fails to find it. Common examples can be a splash activity with no layout to show an animation, or a broadcast receiver which should load after intent is received, like boot completed intent.

What is common on these cases is that these classes should be configured on the AndroidManifest.xml file as part of the build process, but during the application load lifecycle, these classes are not found. This indicates that there is missing metadata which affects the load process. Let’s review a common application manifest and class declaration and discuss the problem and solution.


AndroidManifest


<manifest package="com.ozkary.app"
<receiver       
        android:name=".BootReceiver"    
<intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />  
</intent-filter>

</receiver>
</manifest>


On the abbreviated manifest above, we can find the package name and the receiver class.  The receiver class name is relative to the package name which means that during the load time, the class loader will attempt to find a class with the name of com.ozkary.app.BootReceiver.

When the class not found exception is raised, we need to take a look at how our project metadata is getting created. This is where our class attributes become very important for our builds.


Class Metadata with Attributes

During the class implementation phase, we can leverage class attributes to add metadata information to our projects. For a Xamarin Android project, this is very important because this is the metadata that is added to the AndroidManifest file during the build cycle. With that knowledge in mind, let’s take a look at how we should properly declare our class.


[BroadcastReceiver(Name = "com.ozkary.BootReceiver]
[IntentFilter(new[] { Intent.ActionBootCompleted })]
public class BootReceiver : BroadcastReceiver


By looking at our abbreviated class declaration, we are setting the receiver class name properly as well as the intent. When we build the project, the metadata generated from our classes is merged with the Properties/AndroidManifest.xml file.  This is true for all classes including activities.

When encountering this Class Not Found Exception, we should review the content of the manifest file as well our class declarations, and we should find that there is probably not enough metadata added to the classes to prevent this error.


I hope this helps some of you with this problem.

Originally published by ozkary.com

5/19/18

Xamarin Android Build Java Exited with Code 1 ProGuard

When building a Xamarin Android app and using the option to Enable ProGuard, we may get the following error:


error MSB6006: "java.exe" exited with code 1


Note: Proguard is a file shrinker/optimizer which is often used on a release version. This can be found on the Android Options tab.



The error means that java is not able to build the application due to some an error that is raised during the build process. To find out what the error details, we need to set the MSBuild verbosity mode to Diagnostic which provides detail log on each step during the build. We can change the verbosity mode from Visual Studio Build and Run settings which can be found on the following menu option:

Tools->Options->Project and Solutions-Build and Run



Once this option is set, we should be able to compile again and see more detail about what is happening. If we look at the MSBuild output (output window on Visual Studio), we can find the error or exception that can provide more insight on the problem.

For this case, we can see that there is an error associated to the proguard tool. The error reads that there is an unknown option on the configuration file proguard.cfg.


proguard.ParseException: Unknown option '∩┐-dontwarn' in line 1 of file 'proguard.cfg', (TaskId:226)


If we look carefully, we can see that there is a funny character on the error message.  This leads us to think that there is some junk data in the proguard.cfg file, or there is an encoding problem.

Solution:

The proguard tool does not handle files that contain Byte Order Mark BOM. Visual Studio creates files with this information. The BOM is used to indicate the file encoding type. To see and remove that encoding, use a tool like Notepad++ and save the file without the BOM encoding which is a menu option when saving the file.

After removing the BOM from the file, we should be able to build the project again and see a successful build. Inspecting the log, we can also see that the proguard task completes with no errors:


Done executing task "Proguard". (TaskId:179)



Hopefully this can help solve similar errors when building Xamarin Android Apps.

Originally published by ozkary.com

5/5/18

Xamarin Android Device Mac and IP Address on a WebView JavaScript App

When using JavaScript applications with any framework, we cannot get access to some of the device information like the MAC and IP Address because JavaScript runs on an Isolated Sandbox due to security concerns.

When building hybrid applications using the WebView control on a Xamarin Android app, we can leverage the nature of the native app layer to provide the device information to the JavaScript layer. There are several ways to enable this interaction/bridge between the Native and JavaScript layers, but there is a more direct integration that can be used to handle this with less effort.

Browser UserAgent

All browsers provide a way to identify their information using the Navigator UserAgent property.  This property tells us the type of browser that is running the application like Internet Explorer, Safari, and Chrome etc.

When using the WebView control on a native app, we have more permission to control this information. This can enable our apps to set a UserAgent property that can provide the JavaScript application with device specific information.  Let’s review how that can be done by looking at a code sample with Xamarin Android project (C#) and JavaScript.

Xamarin Android Project

On the Xamarin Android project, we can set some of the WebView control properties on the OnCreate override of our activity as shown below:


private void SetWebView()
{
    WebView view = FindViewById<WebView>(Resource.Id.webView1);
    view.Settings.JavaScriptEnabled = true;
    view.Settings.UserAgentString = GetDeviceInfo();
}

private static string GetDeviceInfo()
{
    string mac = string.Empty;
    string ip = string.Empty;

    foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (netInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
            netInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        {
            var address = netInterface.GetPhysicalAddress();
            mac = BitConverter.ToString(address.GetAddressBytes());

            IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());                   
            if (addresses != null && addresses[0] != null)
            {
                ip = addresses[0].ToString();
                break;
            }                 

        }
    }



The code loads the reference to the control. This enables us to set the control settings to enable the JavaScript functionality to run on and set the user agent with the device information.

Notice that on the GetDeviceInfo function, we get both the MAC and IP address and return the information as a delimited string similar to the format used by most browsers. This enables us to parse the information and display/use it as needed.

JavaScript Code

When navigating to the web page on the WebView control, we can now query the windows user agent property and request the information that is set by the native code as shown below:


var device = window.navigator.userAgent;
console.log(device);              
 

The console log should print out the content of the string with a pattern similar to aa-bb-cc-dd/100.10.0.0 which represents the MAC and IP address of the device.

Using this approach, we can easily provide device information to the JavaScript app to enable it to display the device MAC and IP address which is usually hidden from the JavaScript layer due to security concerns on the device.

Originally published by ozkary.com