ASP.NET MVC: Constructing UrlHelper

I needed to have a class external to the controller’s and views that could generate a correctly formed Url using the UrlHelper.

I found this question on Stackoverflow which helped me with a solution. The solution was as follows:

HttpContextWrapper httpContextWrapper =
    new HttpContextWrapper(HttpContext.Current);

UrlHelper urlHelper = new UrlHelper(
    new RequestContext(
        httpContextWrapper, 
        new RouteData()));

I previously got confused about the RouteData object, but it seems (unless I’m mistaken) to essentially be route values, which in this case i don’t need… Not sure on that though!

As constructed above, the UrlHelper is able to take the RequestContext and get all the registered routes and therefore generate a correctly structured url when you call Action etc.

ASP.NET Browser Detection Results

Browser detection in ASP.NET 3.5 (and probably older) using Request.Browser information.

This is what I’ve got so far… Hopefully I can expand on it and fill in the rest of the details.

  IE 8 IE 7 IE 6 FireFox 3.6 FireFox 3.5.5 FireFox 3.0.15 Chrome 3.0.195.33
Browser.Browser IE ? IE firefox firefox firefox AppleMAX-Safari
MajorVersion 8 ? 6 3 3 3 5
MinorVersionString .0 ? .0 .6 .5.5 .0.15 .0
MinorVersion 0 ? 0 0.6 0.5 0 0

Generating Uri’s(Url’s) Matching Route in MVC

In the course of trying to get an MVC application working on IIS 6 we we have decided on some rules for generating Uri in an MVC application. The rules seek to ensure that all Uri generated will be correct no matter in what type of environment that we host our application. We are seeking to generate Uri that match a route as there may be situations where clients don’t want’ to use Wildcard Extension Mapping, and some that may, and some that will run it on IIS 7…

I may post something more about that soon, but for the moment I want to focus particularly on the generation of Uri outside of ActionLink and BeginForm etc.

The following code shows how to generate a Uri (in my case I just rendered it as text onto the page for testing purposes. So I did it all on the view.)

    <%
        var routeValues = new RouteValueDictionary(); 
        routeValues.Add("controller", "Home"); 
        routeValues.Add("Action", "Dogs"); 
        routeValues.Add("dogId", "15");  
    %>
    <%= RouteTable.Routes.GetVirtualPath(Html.ViewContext.RequestContext, routeValues).VirtualPath %>

If you have a route like this:

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

        routes.MapRoute(
            "Default",                                              
            "{controller}/{action}/{id}",                           
            new { controller = "Home", action = "Index", id = "" } 
        );

    }

Then you will get a uri of :

    /Home/Dogs?dogId=15

IF on the other hand you have a route like this

    routes.MapRoute(
        "Default",                                              
        "{controller}.aspx/{action}/{id}",                      
        new { controller = "Home", action = "Index", id = "" }  
    );

(Notice the .aspx bit) You will get a Uri like this

    /Home.aspx/Dogs?dogId=15

The reason is that the code generated in the GetVirtualPath method takes into account the available routes in the route table when it generates all of the Uri. In other words it finds a route that matches the route values and then generates the Uri based on the route template (for lack of a better work) This is the same thing that the BeginForm and ActionLink helpers (and others)

The framework helpers also take into consideration whether your application in a virtual directory or not and also taked into consideration the virtual directory name.

So it you are generating Uri that is going to be used across different versions of IIS and you want to allow your application to be used with .aspx or .mvc extension (etc) or even extensionless routes, then you should consider using the build int helpers like BeginForm/EndForm, ActionLink etc and also make sure that when you generate Uri for things like images or links in JavaScript or other places that you use the method above or any related method to generate the URi so that they match one of your routes!

Some of the resources that we’ve used while looking at setup on IIS are in this post. And the place that I found the original code that showed how to generate correct Uri in ASP.NET MVC was here.

Scott Guthrie has a post on Url routing. It’s a bit old and may have a few inaccuracies due to changes in the framework as they developed it. This also might be useful!

A potentially dangerous Request.Form value was detected from the client in ASP.NET WebForms and MVC

This error turns up when you enter input into a text field that contains what looks like markup. For example:

APotentiallyDangerouseRequestFormValue

When you submit you normally would get something like this… ( which unfortunately I copied from the wrong place originally :S )

Server Error in ‘/MyApplication’ Application.


A potentially dangerous Request.Form value was detected from the client (remarks="<code></code>5678,<c…").

Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. You can disable request validation by setting validateRequest=false in the Page directive or in the configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case.

Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (remarks="<code></code>5678,<c…").

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (remarks="<code></code>5678,<c...").]
   System.Web.HttpRequest.ValidateString(String s, String valueName, String collectionName) +8723114
   System.Web.HttpRequest.ValidateNameValueCollection(NameValueCollection nvc, String collectionName) +111
   System.Web.HttpRequest.get_Form() +129
   System.Web.HttpRequestWrapper.get_Form() +11
   System.Web.Mvc.ValueProviderDictionary.PopulateDictionary() +145
   System.Web.Mvc.ValueProviderDictionary..ctor(ControllerContext controllerContext) +74
   System.Web.Mvc.ControllerBase.get_ValueProvider() +31
   System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +53
   System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +109
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +399
   System.Web.Mvc.Controller.ExecuteCore() +126
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +27
   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
   System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +151
   System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +57
   System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +7
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75


Version Information: Microsoft .NET Framework Version:2.0.50727.4016; ASP.NET Version:2.0.50727.4016

 

… which is nice by default, but in some situations where you want people to be able to enter markup of some kind you want to be able to disable this. There are several ways.

WebForms – Per Page

This is a matter of adding the ValidateRequest property to the page directive per page:

<%@ Page Language="c#" … ValidateRequest="false"%>

WebForms -Globally

To turn off validation (which is not recommended unless you need to and know the consequences) is doen by editing the Web.config file’s pages element and adding the validateRequest attribute as shown below:

<system.web> 
  : 
  <pages validateRequest="false" /> 
  : 
</system.web>

MVC – Action

To prevent this error in MVC you can do it per action by applying the ValidateInputAttribute to the action method.

[AcceptVerbs(HttpVerbs.Post)]
[ValidateInput(false)]
public ActionResult EditMyEntity(string newValue)
{  :
}

Note that I also have an entry on the MVC attribute here which discusses this attribute a little more. I think it needs updating though 🙂

Creating Satellite Assemblies for Resources

I found it finally… It’s taken me ages to find this and it was again by accident!

http://msdn.microsoft.com/en-us/library/21a15yht.aspx

Globalization & Localization Issues in ASP.NET

I was looking form some information about Sql Server Globalization and Localization techniques and came across this article which has a nice little tidbit of information which I was not aware of: This has cleared it up.

Codepage conversion issues

When a character is replaced by a question mark (?) character, this is an indication that a codepage conversion issue, has occurred. The question mark (?) is a default character for the codepage conversion and basically means that the operating system does not know how to handle the character value and convert it. It replaces the character value with a question mark (?). This could mean that the character has an invalid value for the codepage or that the codepage that is needed for the conversion is not installed.

Font conversion issues

When a character is replaced by a box, this is an indication that a font conversion issue has occurred. This occurs on the client side when the client does not have the correct font installed to display this character correctly. For example, when a character is from the Japanese charset, and the client does not have the Japanese fonts installed, the Japanese character is displayed as a box.

Reference: http://support.microsoft.com/kb/893663

JQuery Visual Studio documentation only on Debug

I’ve included my scripts using a dynamic method that means Visual Studio can’t determine what scripts are available to a given page.

This removed the code completion for scripts, and I found the code completion helpful especially as I am learning JQuery and also due to the fact that you can never remember everything 🙂 I also wanted to prevent the script loading when

To get around this issue I’ve included the scripts like this

<% #if DEBUG %>
<!-- Load VS JQuery documentation if in debug mode! -->
<script src="../../Scripts/jquery-1.3.2-vsdoc.js" type="text/javascript"></script>
<% #endif %>

Which ensures that the Script include is only included in DEBUG builds… this means that when I would go to production that script would not be included in the page…

This doesn’t seem (at the moment) to cause issues with the real registration of JQuery… It’s not the most perfect, but it’s a safeguard  against me forgetting 🙂

Update: It’s actually not being found at runtime… So maybe that is why it is not causing issues 🙂