Custom Page and User Control base Classes in MVC

Justin Grant’s solution to this was really appreciated.

I’ve just been having a bit of an issue with User Controls though. and found out that the Inherits attribute on page and control are not needed. When I inherited from the class on a page I was fine, but Inheriting from the User Control class gave me errors.

So the following will work and give you code completion…

For Pages:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" %>

For Controls:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Example.ascx.cs" %>

Advertisements

Getting a RequestContext outside of the Controllers and Views in MVC

Just a simple example of how to get the RequestContext when you are not in the context of a controller or a view.

        public static RequestContext GetRequestContext()
      {
           HttpContextBase context = new HttpContextWrapper(HttpContext.Current);
           return new RequestContext(context, RouteTable.Routes.GetRouteData(context));
      }

References:
http://stackoverflow.com/questions/1082748/generating-urls-form-mvc-routes-in-a-management-layer

Posted in Uncategorized. Tags: . 1 Comment »

Controllers in another Assembly in MVC

I was looking for information about putting controllers in a seperate assembly(dll) as a test to see whether I would be able to create some sort of plugin mechanims where the plugin assembly contains the controllers needed for that plugin.

I came across this post in a forum which simply stated says that you need to do this:

  1. Create your web application
  2. Create your class library for your controllers
    1. Reference the System.Web.Extensions.dll
    2. Reference the System.Web.MVC.dll
  3. From your web application, reference the class library

And that is it! You can create your controllers in the class library and everything will just work (Except you won’t be able to right click on an action and click “Add View…” and some of the other nice thing like that!)

It seems that the MVC framework looks in the whole appdomain for any class that implements IController…

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 🙂

Mono MasterPage Issues in MonoDevelop

I was trying to get a MonoDevelop MVC application up and running and came across this little snag.The error was:

"The view 'Index' or its master could not be found"

The Index.aspx view existed, but it was linked to a MasterPage like this:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Views/Shared/MasterPage.master" %>

I added this to the Web.config file:

<pages pageBaseType="System.Web.UI.Page">

And the issue went away.