Windows 2012 Hosting - MVC 6 and SQL 2014 BLOG

Tutorial and Articles about Windows Hosting, SQL Hosting, MVC Hosting, and Silverlight Hosting

ASP.NET MVC 4 Hosting - Adaptive Rendering in ASP.NET MVC 4

clock April 25, 2013 08:50 by author andy_yo

Adaptive Rendering also called responsive design taking the advantage of existing HTML markup and CSS to use inside the ASP.NET Web applications. This post outlines about Adaptive Rendering, display modes and out of the box ASP.NET MVC mobile template. What is unique about .NET 4.5 application templates that ships out-of-the box uses a technique called responsive design. Responsive design is functionality of CSS to redefine the layout properties of your page based on the web and devices that you are using.

About ASPHostPortal.com
ASPHostPortal.com is Microsoft No #1 Recommended Windows and ASP.NET Spotlight Hosting Partner in United States. Microsoft presents this award to ASPHostPortal.com for ability to support the latest Microsoft and ASP.NET technology, such as: WebMatrix, WebDeploy, Visual Studio 2012, ASP.NET 4.5, ASP.NET MVC 4.0, Silverlight 5 and Visual Studio Lightswitch. Click here for more information

The desktop experience of the default ASP.NET MVC4 application after running and resizing the browser windows looks as below


Once you are under 850 pixel width restriction, CSS will automatically compute with new set of rules for rendering the screen , it is standard CSS nothing specific to .NET.


Display Modes

Add a new view to your ASP.NET MVC 4 project called Index.mobile


Instead of building the mobile view from scratch, take index view mark up and paste in the new view and browse the view in mobile emulator and it will render you .index.mobile.cshtml page

what if you want to customise the view to specific type of device or model, you can do this inside Visual Studio. Open the Global.asax file and register the new view type with display mode provider as shown below

insert the display mode at the beginning of the stack.The contextcondition can be based on cookies, user context and headers as long as the result resolved to true or false. Now create a  new view index.WindowsPhone.cshtml in your project and change the header text so that you know it is your custom display mode, now run the application with browser you will get index.cshtml view, run with specific device emulator then you will get that index.windowsphone.cshtml view as shown below

so you can use the same URL to target different devices based on custom view and criteria.

Mobile Template

You have new template for Mobile Web applications in ASP.NET 4.5 MVC, create a new project and select the Mobile Template as shown below

Now run the application in browser for desktop view, you will notice that look is mobilish…. and then run in mobile emulator and it looks as below

It uses the JQuery UI to render the elements.If you open the index file then you will notice some html attributes that are specific to JQuery UI.



ASP.NET MVC 4 Hosting - ASPHostPortal :: Multiple Views and DisplayMode Providers in ASP.NET MVC 4

clock April 8, 2013 12:35 by author Jervis

All in all, the biggest difference between ASP.NET MVC and ASP.NET Web Forms is the neat separation that exists in ASP.NET MVC between the actions that follows a request and the generation of the subsequent response for the browser.

The request lifecycle In Web Forms was a continuous flow. Firstly, a Page object was created from default settings hard-coded in the ASPX file and then initialized to the last known good state read from the viewstate field. The user code had then a chance to further update the state of the Page object before the postback event was handled and the state of the page to render back to the user was prepared.

All this happened in a single procedure: There was little chance for developers to serve different views in front of the same request. On the other hand, Web Forms is built around the concept of a “page”. If you request a page, you’re going to get “that” page. Subsequently, if you request default.aspx from a site intended for desktop use why should you be expecting to receive a mobile optimized page instead if you’re making the request from a mobile device? If you want a mobile page, you just set up a new mobile site and make it reachable through a different URL. At that point, you have a distinct “page” to invoke and it all works as expected.

Web Forms at some point was also extended with convention-based tricks to automatically serve different master pages to different browsers and also to make server controls capable of returning different values for different browsers. Nevertheless, Web Forms serves the vision of the web world that was mainstream more than a decade ago. Unless you have serious backward compatibility reasons, you should definitely consider making the step forward to ASP.NET MVC; and use ASP.NET MVC for any new development.

Anyway, this article is NOT about the endless debate the relative merits of Web Forms and MVC—there’s really nothing to discuss there. This article is about new features introduced in ASP.NET MVC 4 to make it really easy and effective to serve different views in front of the same request.

Display Modes

Here’s the classic example where display modes fit in. Suppose you have a Home controller with an Index method.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

As you know, you should also have a file named index.cshtml located under the Views/Home folder in the project. This file will provide the HTML for the browser. In the body of the Index method above you code (or better, you invoke from other components) the logic required to serve the request. If, by executing this piece of logic, data is produced which needs to be embedded in the view, then you pass this data down to the view object by adding an argument to the View method.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = ProcessRequestAndGetData();
        return View(model);
    }
}

So far so good.

Now in ASP.NET MVC 4 there’s an extra piece of magic that you might not know about yet. To experience the thrill of it, you add a new file to the Views/Home folder named index.mobile.cshtml. You can give this file any content you like; just make sure the content is different from the aforementioned index.cshtml.

Now launch the sample site and visit it with both a regular desktop browser, Internet Explorer perhaps, and a mobile browser. You can use the Windows Phone emulator or perhaps Opera Emulator. However, the simplest thing you can do to test the feature without much pain is to hit F12 and bring up the IE Developer’s Tools window. From there, you set a fake user agent that matches a mobile device. If you are clueless about what to enter, here’s a suggestion that matches an iPhone running iPhone OS 6:

Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko)

Quite surprisingly, the view you get for the same home/index URL is the mobile view as coded in the file index.mobile.cshtml.

What the heck is going on? Is this pure magic?

Even though I’m a firm believer that there can’t be any magic in software, well, I faced some terrible doubts until I found out about display modes.

Display Modes: Where Are Them?

To spot where display modes are and the role they play, I then used .NET Reflector to statically track the code path starting with the View method on the Controller class. From the View method, the code flow reaches the selected view engine—the RazorViewEngineclass in all cases in which CSHTML views are used. In ASP.NET MVC 4 all standard view engines inherit from the same base class—VirtualPathProviderViewEngine. This class has a new protected property named DisplayModeProvider. This property is of typeDisplayModeProvider. TheVirtualPathProviderViewEngine lists some helper methods through which the view name is resolved. The view engine receives the view name as set at the controller level: it can be name like “index” or it can be the empty string, as in the example above. If no view name is provided the view engine assumes it is the name of the action.

In ASP.NET MVC 4, an extra step takes place in theVirtualPathProviderViewEngine base class from which both WebFormsViewEngine and RazorViewEngine inherit. During the resolution of the view name, the view engine queries theDisplayModeProvider object to see if any of the registered display modes can be applied to the requested view. If a match is found, then the original view name is changed to point to the CSHTML file that represents the match. So, for instance, it may happen that “index” becomes “index.mobile”.

Let’s now explore further the internals of the DisplayModeProvider class.

The DisplayModeProvider Class

The documentation refers to this class as being internal to the framework; however, it has a few public members that you might, and should, be using in order to extend your site with multiple ad hoc views. The class has a static constructor that .NET Reflector decompiles as below:

static DisplayModeProvider()
{
    MobileDisplayModeId = "Mobile";
    DefaultDisplayModeId = string.Empty;
    _displayModeKey = new object();
    _instance = new DisplayModeProvider();
}

And here’s the constructor instead:

internal DisplayModeProvider()
{
    List list = new List();
    DefaultDisplayMode mode = new DefaultDisplayMode(MobileDisplayModeId) {
        ContextCondition = context => context.GetOverriddenBrowser().IsMobileDevice
    };
    list.Add(mode);
    list.Add(new DefaultDisplayMode());
    this._displayModes = list;
}

It turns out that DisplayModeProvider holds a list of DefaultDisplayMode objects each representing a display mode. By default, the provider holds two display modes: default and mobile. The default display mode is characterized by the empty string; the mobile display mode is characterized by the “mobile” string. These strings basically identify the suffix appended to the view name. This is where file name index.mobile.cshtml comes from.

It is interesting to focus on the following code:

DefaultDisplayMode mode = new DefaultDisplayMode(MobileDisplayModeId) {
     ContextCondition = context =>
context.GetOverriddenBrowser().IsMobileDevice
};

In spite of a misleading name, the DefaultDisplayMode class is just the official class that represents a display mode. As I see things, the “Default” prefix in the name is just out of place. A display mode class is built around two main pieces of information: suffix name and matching rule. In the code snippet above, a new display mode class is created with the suffix of “mobile”—the actual value of the MobileDisplayModeIdfield—and a matching rule assigned to the ContextConditionproperty. Property ContextCondition is a delegate as below:

Func<HttpContextBase, Boolean>

The purpose of the delegate is to analyze the HTTP context of the current request and return a Boolean answer to the question: should this display mode be used to serve the current request? How the Boolean response is found is entirely up to the implementation. As defined above, the mobile display mode parses the user agent string that comes with the request and seeks to find known keywords that would mark it for that of a mobile device. I’ll return on this point in a moment.

Listing Current Display Modes

You hardly have the need to do this in code, but I encourage you to try that out for pure fun. Here’s the code that reads and displays the currently available modes:

<ul>
    @{
        foreach(var d in DisplayModeProvider.Instance.Modes)
        {
            <li>@(String.IsNullOrEmpty(d.DisplayModeId) ?"default" :d.DisplayModeId)</li>
        }
    }
</ul>

You use the Instance static member to access the singleton instance of the DisplayModeProvider class and flip through the Modes property. By the way, the getter of the Modes property just returns the value stored in the internal _displayModes field dissected earlier through .NET Reflector.

Beyond the Default Configuration

The default and mobile display modes come free out of the box, but honestly they are not worth the cost. I have two reasons to say this. First, modern web sites need more than just a mobile/desktop dichotomy for views. You might want to distinguish tablets, smartphones, legacy phones, perhaps smart TVs. Sometimes this can be achieved with CSS media queries; sometimes you need to do server-side detection of the device via its provided user agent string. This leads to the second reason I have to blissfully ignore the default ASP.NET MVC configuration. Even if a plain desktop/mobile dichotomy works for your site, the point is that the logic behind the mobile context condition is weak and flaky. It has good chances to work with iPhone and BlackBerry devices; it may not even work with Windows Phone and Android devices—let alone with older and simpler devices. The method IsMobileDevice you have seen referenced a while back does sniffing of the user agent string based on the information it can find in the following .browser files you get installed with ASP.NET.

The model is clearly extensible and you can add more information at any time; but writing a .browser file may not be easy and the burden of testing, checking, and further extending the database is entirely on your shoulders.

The figure proves that I added a fairly large (18 MB) browser file—an XML file actually—named mobile.browser. That file comes from an old Microsoft project now discontinued and contains a reasonable amount of devices as of summer of 2011. All devices and browsers which came next are not correctly detected.

In the end, display modes are an excellent piece of infrastructure but require a bit of work on your end for configuration and additional tools to do view routing work effectively. The siren call about ASP.NET MVC being fully mobile aware is just a siren call.

What Can You Do About It?

You use display modes to give your site multiple views in front of the same URL. More concretely, this mostly means using defining a display mode for each device, or class of devices, you’re interested in. You could create an iPhone display mode for example. Likewise, you could create a tablet display mode. Here’s some code:

var modeTablet = new DefaultDisplayMode("tablet")

{
   ContextCondition = (c => IsTablet(c.Request))
};var modeDesktop = new DefaultDisplayMode("")
{
   ContextCondition = (c => return true)
};
displayModes.Clear();
displayModes.Add(modeTablet);
displayModes.Add(modeDesktop);

When run from Application_Start, the code drops default modes and defines two new modes: tablet and desktop. The tablet mode is added first and will be checked first. The internal logic that finds the appropriate display mode, in fact, stops at first match. If the HTTP request is not matched to a tablet, it is then treated by default with a view optimized for a desktop device.

How would you reliably determine whether a given request comes from a tablet? It’s all about sniffing the user agent string; but you need a professional tool for that. The answer is getting a commercial license from a Device Description Repository vendor like ScientiaMobile for WURFL. Note that WURFL is only the most widely used (Facebook and Google use it) device database; it is free for open source projects and has a partly free cloud version. Other products exist too. But my point here is that you should not spend a second on crafting your own solution for sniffing user agent strings.

 



ASP.NET MVC 4 Hosting - Overriding Browser Capabilities in MCV 4

clock March 4, 2013 09:31 by author andy_yo

The new System.Web.WebPages 2.0.0.0 assembly that ships with the latest MVC4 contains a pretty cool feature that lets you override the current browser capabilities. Sure, most modern browsers let you set a custom user agent string out of the box or via extensions. However, there are certain scenarios, where you would want to switch the user agent on the server side. That’s where the BrowserHelpers class comes in handy.

Override Browser Context

A good example where you want to use override the browser capabilities is when developing mobile views. You may not want to simulate a particular device, you just want to tell ASP.NET that the client is a mobile device and to use the .mobile view.  You can call SetOverridenBrowser extension method and pass in BrowserOverride enum (Mobile/Desktop options).

public ActionResult Mobile()
{
    HttpContext.SetOverriddenBrowser(BrowserOverride.Mobile);
    return RedirectToAction("Index");
}

If you want, you can override the browser full UserAgent by calling SetOverridenBrowser extension method on HttpContextBase

public ActionResult Iphone()
{
  HttpContext.SetOverriddenBrowser("Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7");
    return RedirectToAction("Index");
}

And then, in order the clear the override, simple call the ClearOverridenBrowser extension method

public ActionResult Clear()
{
    HttpContext.ClearOverriddenBrowser();
    return RedirectToAction("Index");
}

What is happening under the hood

When you call the SetOverridenBrower method, ASP.NET sets a “.ASPXBrowserOverride” cookie. This is done using CookieBrowserOverrideStore from System.Web.Webpages, which implements BrowserOverrideStore – if you’re interested, check it out in dotpeek.

The value of the cookie is the user agent that you have set or in the case of the BrowserOverride.Mobile enum: Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile 6.0). The expiry date is set for 7 days so the override will be in place even if you re-open your browser. Calling ClearOverridenBrowser simply clears the cookie.

Create Mobile Switched Filter

The jQuery.Mobile.MVC package comes with the ViewSwitcher razor partial and the ViewSwitcherController. This does more or less exactly what I described above. However, if you are lazy like me, you may want to switch between mobile/desktop views using QueryString rather than controller/actions.  This is useful when you want to just quickly check your mobile views.

public class BrowserCapabilitiesSwitcherFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var switchParameter = filterContext.RequestContext.HttpContext.Request.QueryString["switch"];
        if(string.IsNullOrEmpty(switchParameter))
            return;
        var browserOverride = BrowserOverride.Desktop;
        if(Enum.TryParse(switchParameter, true, out browserOverride))
        {
            //switch between BrowserOverride.Desktop / BrowserOverride.Mobile
            filterContext.RequestContext.HttpContext.SetOverriddenBrowser(browserOverride);
        }
        else
        {
            //set the user-agent string
            filterContext.RequestContext.HttpContext.SetOverriddenBrowser(switchParameter);
        }           
    }
}

Simply use it by typing http://yoursite.com/page?switch=Mobile to preview in mobile and then http://yoursite.com/page?switch=Desktop to switch back. For the more adventurous, you can pass in the user agent directly http://yoursite.com/page?switch=UserAgentString

 

 



ASP.NET MVC 4 Hosting - Razor 2.0 Features in ASP.NET MVC 4

clock February 19, 2013 12:26 by author andy_yo

First version of razor is shipped with ASP.NET MVC 3. ASP.NET MVC 4 come with Razor V2.0. Razor V2.0 includes some new features.

About ASPHostPortal.com
ASPHostPortal.com is Microsoft No #1 Recommended Windows and ASP.NET Spotlight Hosting Partner in United States. Microsoft presents this award to ASPHostPortal.com for ability to support the latest Microsoft and ASP.NET technology, such as: WebMatrix, WebDeploy, Visual Studio 2012, ASP.NET 4.5, ASP.NET MVC 4.0, Silverlight 5 and Visual Studio Lightswitch. Click here for more information

 

URL Resolution Enhancements:

We use the relative URL for any resources (images, scripts, css) in code , for example :

<script src=”~/Scripts/jquery-1.8.2.js”></script>

But in runtime we should resolve the full path of the resource (absolute URL), to do this in ASP.NET MVC 3 we use Content() method of UrlHelper class.

<script src=’@Url.Content(“~/Scripts/jquery-1.8.2.js”)’></script>

In Razor V2.0 no need to use @Url.Content() method, razor v2.0 now resolves (absolute path/URL) ~/ (tilde-slash) within all standard HTML attributes, razor v2.0 now allows you to just write  :

<script src=”~/Scripts/jquery-1.8.2.js”></script>

Conditional Attribute Enhancements:

Hers is a classic example for conditional attributes, I have a <div> tag with class attribute. The class name is a dynamic value, It will be resolved at runtime based on some condition in razor code. If the condition is satisfied  class attribute will have some value, else it will be null. When there is a value no issues, but when value is null  we should not apply it for class attribute, to be strict when there is no value for class attribute we should not render it. This scenario involves with writing some ugly code with if condition & <text> tag, in Razor1.0 (ASP.NET MVC 3) code snippet as follows.

 

In Razor 2.0 (ASP.NET MVC 4) now we can write:

 

 

Above code returns the same results as earlier, for example if the @ViewBag.UseRoundCorners value is true, then myClass value is roundCorners, then  razor will render :

<div class=”roundCorners ”></div>

If @ViewBag.UseRoundCorners value is false, then myClass value is null, then razor will render <div> tag with out class attribute:

<div></div>

Razor V2.0 can handle multiple values in conditional attributes:

For example class attribute has multiple values <div class=”@myClass heading”></div>, now razor will render <div class=”roundCorners  heading”></div> if @myClass is not null, if @myClass is null, then razor will simply render <div class=”heading”></div>.

Razor V2.0  can handle Boolean values in conditional attributes:

Not only null values & multiple values, razor can handle boolean values also in conditional attributes.

<input type=”checkbox”  checked=”@ViewBag.Checked” />

If @ViewBag.Checked value is true then razor will render:

<input type=”checkbox”  checked=”checked” />

If @ViewBag.Checked value is false then razor will render:

<input type=”checkbox”  />



ASP.NET MVC 4 Hosting - ASPHostPortal :: Getting WebApi and Areas to play nicely ASP.NET MVC 4

clock January 21, 2013 07:08 by author Jervis

In this blog, I discuss these limitations and present a possible solution.

Background

The WebApi and Areas features play an important role in the project I am currently working on. In this project, a web application is developed for multiple types of end-users. Areas are used to create separate frontends for each type of end-user. WebApi is used as part of an interaction framework (knockoutjs) that enriches the user experience. Below is a list of relevant design decisions that were made:

- The main MVC application resides in the root of the solution.
- All administrator functionality resides in a separate area.
- Each external party has its own area.
- Each area, including the root, constitutes a well separated functional block. Functionality from one area may not be exposed to another area. This is to prevent unauthorized access of data.
- Each area, including the root, has its own RESTfull API (WebApi).

During the development of this web application, I encountered an important limitation of WebApi when used in conjunction with Areas.

Routing and WebApi

Both regular and WebApi calls use ASP.NET MVC’s routing mechanism to translate HTTP requests to the appropriate controller action. However, only regular calls support areas, while WebApi calls are “arealess”. As a result, WebApi controllers in different areas are actually accessible from all areas. Additionally, having multiple WebApi controllers with identical names in different areas will produce an exception:

Multiple types were found that match the controller named ‘clients’. This can happen if the route that services this request (‘api/{controller}/{id}’) found multiple controllers defined with the same name but differing namespaces, which is not supported.

The request for ‘clients’ has found the following matching controllers:
MvcApplication.Areas.Administration.Controllers.Api.ClientsController
MvcApplication.Controllers.Api.ClientsController

The error message pretty much sums up the problem: ASP.NET MVC 4 RC does not support the partitioning of WebApi controllers across areas.

IHttpControllerSelector

The culprit is the DefaultHttpControllerSelector which is ASP.NET MVC’s default implementation of the IHttpControllerSelector interface. This class is responsible for selecting the appropriate IHttpController (the interface implemented by ApiController), when provided with a HTTP request message. At the heart of the DefaultHttpControllerSelector lies the HttpControllerTypeCache. This class runs through all assemblies that are used by the application and caches all types that implement the IHttpController. The SelectController method of the DefaultHttpControllerSelector uses this cache to lookup a matching type for the given controller name. This operation can end in three different manners:

- No matching types were found, which results in an HttpStatus.NotFound (404).
- One matching type was found, which is returned by the method and ASP.NET MVC continues to process the request.
- Multiple matches were found, which results in an exception similar to one displayed earlier.

In search for a solution

Fortunately, through the power of Inversion of Control, developers can inject their own implementation of IHttpControllerSelector. In a related blog by Andrew Malkov, he attempts to tackle the problem by creating a custom implementation called AreaHttpControllerSelector.

This class allows area specific WebApi controllers to co-exist, provided one makes a minor modification to the WebApi routes. In order to function, a default route parameter called “area” must be added to the HttpRoute definition in the AreaRegistration file.

1              context.Routes.MapHttpRoute(
2                  name: "Administration_DefaultApi",
3                  routeTemplate: "Administration/api/{controller}/{id}",
4                  defaults: new { area = "Administration", id = RouteParameter.Optional }
5              );

Unfortunately, adding this extra parameter introduces a new limitation: Querystring parameters on WebApi calls no longer function. E.g. GET /Administration/api/clients will work, but GET /Administration/api/clients?firstname=john will result in a 404.

Part of the problem lies in the manner in which AreaRegistration is used to define routes. Consider the AdministrationAreaRegistration below:

1              public class AdministrationAreaRegistration : AreaRegistration
2              {
3                  public override string AreaName
4                  {
5                      get
6                      {
7                          return "Administration";
8                      }
9                  }
10          
11               public override void RegisterArea(AreaRegistrationContext context)
12               {
13                   context.Routes.MapHttpRoute(
14                       name: "Administration_DefaultApi",
15                       routeTemplate: "Administration/api/{controller}/{id}",
16                       defaults: new { id = RouteParameter.Optional }
17                   );
18          
19                   context.MapRoute(
20                       "Administration_default",
21                       "Administration/{controller}/{action}/{id}",
22                       new { action = "Index", id = UrlParameter.Optional }
23                   );
24               }
25           }

The first route defines how ApiContollers can be reached, while the second route defines how regular controllers can be reached. Both registrations use a different method for registering the route in order to differentiate between normal calls and WebApi calls. Routes registered through MapHttpRoute are meant for WebApi controllers while routes registered through MapRoute are meant for regular controllers.

Note that MapHttpRoute is called on the Routes collection, whereas MapRoute is called on the AreaRegistrationContext itself. This implies that there is a difference between the default MapRoute and the one provided by the AreaRegistrationContext.

After digging through the sourcecode of ASP.NET MVC, I found that the most notable difference is that the MapRoute of AreaRegistrationContext incorporates the AreaName into the route’s metadata. Specifically, the value of the AreaName property is added to the route’s DataTokens.

Solution – Part 1

I created a MapHttpRoute extension method for the AreaRegistrationContext that performed a similar operation as the AreaRegistrationContext.MapRoute method.

1              public static class AreaRegistrationContextExtensions
2              {
3                  public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate)
4                  {
5                      return context.MapHttpRoute(name, routeTemplate, null, null);
6                  }
7             
8                  public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate, object defaults)
9                  {
10                   return context.MapHttpRoute(name, routeTemplate, defaults, null);
11               }
12          
13               public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate, object defaults, object constraints)
14               {
15                   var route = context.Routes.MapHttpRoute(name, routeTemplate, defaults, constraints);
16                   if (route.DataTokens == null)
17                   {
18                       route.DataTokens = new RouteValueDictionary();
19                   }
20                   route.DataTokens.Add("area", context.AreaName);
21                   return route;
22               }
23           }

To use the new extension method, remove the Routes property from the call chain:

1              context.MapHttpRoute(
2                name: "Administration_DefaultApi",
3                routeTemplate: "Administration/api/{controller}/{id}",
4                defaults: new { id = RouteParameter.Optional }
5              );

Now both the regular routes and the WebApi routes have knowledge of their corresponding area.

Solution – Part 2

The second part of the solution is to create an implementation of IHttpControllerSelector that actually uses the area name. I took the AreaHttpControllerSelector class from Andrew Malkov’s blog post and used it as a base for my own solution.

1              namespace MvcApplication.Infrastructure.Dispatcher
2              {
3                  using System;
4                  using System.Collections.Concurrent;
5                  using System.Collections.Generic;
6                  using System.Globalization;
7                  using System.Linq;
8                  using System.Net.Http;
9                  using System.Web.Http;
10               using System.Web.Http.Controllers;
11               using System.Web.Http.Dispatcher;
12          
13               public class AreaHttpControllerSelector : DefaultHttpControllerSelector
14               {
15                   private const string AreaRouteVariableName = "area";
16          
17                   private readonly HttpConfiguration _configuration;
18                   private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerTypes;
19          
20                   public AreaHttpControllerSelector(HttpConfiguration configuration)
21                       : base(configuration)
22                   {
23                       _configuration = configuration;
24                       _apiControllerTypes = new Lazy<ConcurrentDictionary<string,
Type>>(GetControllerTypes);
25                   }
26          
27                   public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
28                   {
29                       return this.GetApiController(request);
30                   }
31          
32                   private static string GetAreaName(HttpRequestMessage request)
33                   {
34                       var data = request.GetRouteData();
35                       if (data.Route.DataTokens == null)
36                       {
37                           return null;
38                       }
39                       else
40                       {
41                           object areaName;
42                           return data.Route.DataTokens.TryGetValue(AreaRouteVariableName, out areaName) ? areaName.ToString() : null;
43                       }
44                   }
45          
46                   private static ConcurrentDictionary<string, Type> GetControllerTypes()
47                   {
48                       var assemblies = AppDomain.CurrentDomain.GetAssemblies();
49          
50                       var types = assemblies
51                           .SelectMany(a => a
52                               .GetTypes().Where(t =>
53                                   !t.IsAbstract &&
54                                   t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase) &&
55                                   typeof(IHttpController).IsAssignableFrom(t)))
56                           .ToDictionary(t => t.FullName, t => t);
57          
58                       return new ConcurrentDictionary<string, Type>(types);
59                   }
60          
61                   private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
62                   {
63                       var areaName = GetAreaName(request);
64                       var controllerName = GetControllerName(request);
65                       var type = GetControllerType(areaName, controllerName);
66          
67                       return new HttpControllerDescriptor(_configuration, controllerName, type);
68                   }
69          
70                   private Type GetControllerType(string areaName, string controllerName)
71                   {
72                       var query = _apiControllerTypes.Value.AsEnumerable();
73          
74                       if (string.IsNullOrEmpty(areaName))
75                       {
76                           query = query.WithoutAreaName();
77                       }
78                       else
79                       {
80                           query = query.ByAreaName(areaName);
81                       }
82          
83                       return query
84                           .ByControllerName(controllerName)
85                           .Select(x => x.Value)
86                           .Single();
87                   }
88               }
89          
90               public static class ControllerTypeSpecifications
91               {
92                   public static IEnumerable<KeyValuePair<string, Type>> ByAreaName(this IEnumerable<KeyValuePair<string, Type>> query, string areaName)
93                   {
94                       var areaNameToFind = string.Format(CultureInfo.InvariantCulture, ".{0}.", areaName);
95          
96                       return query.Where(x => x.Key.IndexOf(areaNameToFind, StringComparison.OrdinalIgnoreCase) != -1);
97                   }
98          
99                   public static IEnumerable<KeyValuePair<string, Type>> WithoutAreaName(this IEnumerable<KeyValuePair<string, Type>> query)
100                 {
101                     return query.Where(x => x.Key.IndexOf(".areas.", StringComparison.OrdinalIgnoreCase) == -1);
102                 }
103        
104                 public static IEnumerable<KeyValuePair<string, Type>> ByControllerName(this IEnumerable<KeyValuePair<string, Type>> query, string controllerName)
105                 {
106                     var controllerNameToFind = string.Format(CultureInfo.InvariantCulture, ".{0}{1}", controllerName, AreaHttpControllerSelector.ControllerSuffix);
107        
108                     return query.Where(x => x.Key.EndsWith(controllerNameToFind, StringComparison.OrdinalIgnoreCase));
109                 }
110             }
111         }

If you want to learn more about the technical details of the solution, I suggest you read Andrew’s excellent blog post first. The most significant modifications are:

Changed the GetAreaName method in order to retrieve the area name from the DataTokens property rather than the RouteData.

Added support for “arealess” WebApi controllers (e.g. those that reside in the root) to the GetControllerType method.

Removed the fallback mechanism from the SelectController method. The original implementation would call the SelectController method of the base-class in case GetControllerType failed to produce a result. I preferred an approach where the responsibility of successful controller selection resided in AreaHttpControllerSelector.

Finally, to inject the new AreaHttpControllerSelector class, the following line must be added to the Application_Start method in the Global.asax.cs

1              GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new AreaHttpControllerSelector(GlobalConfiguration.Configuration));

After these modifications everything worked as expected!

 



ASP.NET MVC 4 Hosting - ASPHostPortal :: Implementing custom XmlMediaTypeFormatter that ignores XML namespaces

clock December 21, 2012 10:25 by author Jervis

In this blog post I will show how to implement a custom XmlMediaTypeFormatter that extends the default ASP.NET Web API XmlMediaTypeFormatter in a way that it ignores XML namespaces when parsing xml messages.

By default the ASP.NET Web API XmlMediaTypeFormatter is not able to parse XML requests that contain any XML namespace declarations. If you would like to support clients, that (for any reason) send messages containing XML namespaces you can use the IgnoreNamespacesXmlMediaTypeFormatter that is defined as follows:

public class IgnoreNamespacesXmlMediaTypeFormatter : XmlMediaTypeFormatter
{
  // See http://wiki.tei-c.org/index.php/Remove-Namespaces.xsl
  private const string NamespaceRemover =
    @"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
        <xsl:output method='xml' indent='no'/>
        <xsl:template match='/|comment()|processing-instruction()'>
          <xsl:copy>
            <xsl:apply-templates/>
          </xsl:copy>
        </xsl:template>
        <xsl:template match='*'>
          <xsl:element name='{local-name()}'>
            <xsl:apply-templates select='@*|node()'/>
          </xsl:element>
        </xsl:template>
        <xsl:template match='@*'>
          <xsl:attribute name='{local-name()}'>
            <xsl:value-of select='.'/>
          </xsl:attribute>
        </xsl:template>
      </xsl:stylesheet>";

  private readonly XslCompiledTransform _xlstTransformer;

  public IgnoreNamespacesXmlMediaTypeFormatter()
  {
    var xslt = XDocument.Parse(NamespaceRemover, LoadOptions.PreserveWhitespace);
    _xlstTransformer = new XslCompiledTransform();
    _xlstTransformer.Load(xslt.CreateReader(), new XsltSettings(), new XmlUrlResolver());
  }

  public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
  {
    try
    {
      // Read XML
      var xmlDocument = XDocument.Load(new XmlTextReader(stream));

      // Transform XML
      var resultStream = new MemoryStream();
      _xlstTransformer.Transform(xmlDocument.CreateReader(), XmlWriter.Create(resultStream, new XmlWriterSettings() { OmitXmlDeclaration = true }));
      resultStream.Position = 0;

      // Process request with XmlMediaTypeFormatter default functionality
      return base.ReadFromStreamAsync(type, resultStream, contentHeaders, formatterLogger);
    }
    catch (XmlException)
    {
      return base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);
    }
  }
}

In detail the IgnoreNamespacesXmlMediaTypeFormatter removes the XML namespace declarations from the XML message and passes the modified XML to the base class to use the default XmlMediaTypeFormatter functionality. Removing the XML namespaces is done with a XSLT transformation (see http://wiki.tei-c.org/index.php/Remove-Namespaces.xsl)

To activate the IgnoreNamespacesXmlMediaTypeFormatter add the following lines in the file Global.asax.cs:

protected void Application_Start()
{
  [...]
  // Remove default XmlFormatter and add (customized) IgnoreNamespacesXmlMediaTypeFormatter GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
  var ignoreNamespacesXmlMediaTypeFormatter = new IgnoreNamespacesXmlMediaTypeFormatter{ UseXmlSerializer = true };

GlobalConfiguration.Configuration.Formatters.Add(ignoreNamespacesXmlMediaTypeFormatter);
  [...]
}



ASP.NET MVC 4 Hosting - ASPHostPortal :: How to Fix - Could not load type 'System.Web.WebPages.DisplayModes' from assembly 'System.Web.WebPages, Version=2.0.0.0

clock October 24, 2012 08:28 by author Jervis

This is an error message that sometimes you will see when you run your ASP.NET MVC 4.

Could not load type 'System.Web.WebPages.DisplayModes' from assembly 'System.Web.WebPages, Version=2.0.0.0

So, today I will discuss how to fix it on your shared hosting environment. The basic problem is that there is a mixup between MVC 4 Developer Preview and MVC 4 Beta .dlls in the project. To see which version you have right click the .dll file in Windows Explorer and choose Properties->Details. Look for
  'File Version' :

- MVC 4 Developer Preview is version 4.0.10906.0

- MVC 4 Beta is version 4.0.20126.16343

Make sure all says the MVC 4 beta version number (replace the .dlls from a fresh MVC 4 Beta project if necessary) for these files:


- System.Web.Mvc

- System.Web.WebPages
- System.Web.Razor
- System.Web.WebPages.Deployment
- System.Web.WebPages.Razor

Then please kindly retry and it will work fine.
J

If you have problem with your current host and you need to run your ASP.NET MVC 4, please check our site at
http://www.asphostportal.com. You can  start from our HOST ZERO plan.

Reasons why you must trust ASPHostPortal.com

Every provider will tell you how they treat their support, uptime, expertise, guarantees, etc., are. Take a close look. What they’re really offering you is nothing close to what
ASPHostPortal does. You will be treated with respect and provided the courtesy and service you would expect from a world-class web hosting business.

You’ll have highly trained, skilled professional technical support people ready, willing, and wanting to help you 24 hours a day. Your web hosting account servers are monitored from three monitoring points, with two alert points, every minute, 24 hours a day, 7 days a week, 365 days a year. The followings are the list of other added- benefits you can find when hosting with us:


-
DELL Hardware
Dell hardware is engineered to keep critical enterprise applications running around the clock with clustered solutions fully tested and certified by Dell and other leading operating system and application providers.
- Recovery Systems
Recovery becomes easy and seamless with our fully managed backup services. We monitor your server to ensure your data is properly backed up and recoverable so when the time comes, you can easily repair or recover your data.

- Control Panel
We provide one of the most comprehensive customer control panels available. Providing maximum control and ease of use, our Control Panel serves as the central management point for your ASPHostPortal account. You’ll use a flexible, powerful hosting control panel that will give you direct control over your web hosting account. Our control panel and systems configuration is fully automated and this means your settings are configured automatically and instantly.

- Excellent Expertise in Technology
The reason we can provide you with a great amount of power, flexibility, and simplicity at such a discounted price is due to incredible efficiencies within our business. We have not just been providing hosting for many clients for years, we have also been researching, developing, and innovating every aspect of our operations, systems, procedures, strategy, management, and teams. Our operations are based on a continual improvement program where we review thousands of systems, operational and management metrics in real-time, to fine-tune every aspect of our operation and activities. We continually train and retrain all people in our teams. We provide all people in our teams with the time, space, and inspiration to research, understand, and explore the Internet in search of greater knowledge. We do this while providing you with the best hosting services for the lowest possible price.

- Data Center

ASPHostPortal modular Tier-3 data center was specifically designed to be a world-class web hosting facility totally dedicated to uncompromised performance and security
- Monitoring Services
From the moment your server is connected to our network it is monitored for connectivity, disk, memory and CPU utilization – as well as hardware failures. Our engineers are alerted to potential issues before they become critical.

- Network
ASPHostPortal has architected its network like no other hosting company. Every facet of our network infrastructure scales to gigabit speeds with no single point of failure.

- Security
Network security and the security of your server are ASPHostPortal’s top priorities. Our security team is constantly monitoring the entire network for unusual or suspicious behavior so that when it is detected we can address the issue before our network or your server is affected.

- Support Services
Engineers staff our data center 24 hours a day, 7 days a week, 365 days a year to manage the network infrastructure and oversee top-of-the-line servers that host our clients’ critical sites and services.

 



About ASPHostPortal.com

We’re a company that works differently to most. Value is what we output and help our customers achieve, not how much money we put in the bank. It’s not because we are altruistic. It’s based on an even simpler principle. "Do good things, and good things will come to you".

Success for us is something that is continually experienced, not something that is reached. For us it is all about the experience – more than the journey. Life is a continual experience. We see the Internet as being an incredible amplifier to the experience of life for all of us. It can help humanity come together to explode in knowledge exploration and discussion. It is continual enlightenment of new ideas, experiences, and passions


Author Link


Corporate Address (Location)

ASPHostPortal
170 W 56th Street, Suite 121
New York, NY 10019
United States

Sign in