Razor Syntax Quick Reference

by Administrator 15. Januar 2011 09:15

I saw some nice presentations about the MVC Razor engine, however did not see some sort of cheat sheet so far. Luckily Phil Haack posted something in his blog. Check it out here.

Tags: ,

ASP.NET MVC Authentication

by Administrator 10. September 2010 10:07

ASP.NET MVC comes with a ready made attribute that can be applied to actions to specify that the user must either belong to a specific group of users or be a specific user. This requires you to stick to the role provider model.

[Authorize(Roles = "Admin")]
public ActionResult Create()
{
    return View();
}

If you need something else, it's quite easy to get this started. In my case I'm storing just a session token in the cookie, not the username with any group membership information. To accomplish this, I first define forms authentication with a dedicated login page in web.config.


<system.web>
    <authentication mode="Forms">
        <forms loginUrl="~/Login" timeout="2880" />
    </authentication>

    <authorization>
        <deny users="?" />
    </authorization>   
<system.web>

This will define the login page and prevent unauthenticated access. If you call such an application, you will indeed be redirected to the login page, however neither favicon nor scripts/styles will be loaded correctly for this page. When inspecting your http traffic (e.g. using Fiddler), you'll notice requests that go to resources like javascript includes, styles or the favicon being answered with an http 302 object moves response pointing to your login page. To make these resources work, you have to allow anonymous access, because at the point, where you hit your login page your are still anonymous.


<!--
Allow anonymous access to the favicon.
-->
<location path="favicon.ico">
    <system.web>
        <authorization>
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

<!--
Allow anonymous access to the content folder.
-->
<location path="Content">
    <system.web>
        <authorization>
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

<!--
Allow anonymous access to the scripts folder.
-->
<location path="Scripts">
    <system.web>
        <authorization>
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

To take authorization into your own hands, you can implement an attribute similar to the authorize attribute, but with your own desired logic:

public class MyAuthorizationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if(<AuthorizationFails>)
            filterContext.HttpContext.Response.Redirect("/error/401");
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {

    }
}

Action filter attriubtes provide an entry point before and after an action is executed. OnActionExecuting happens before execution. By modifying the response here, you can prevent execution of the action. To use this attribute, just use it on an action.

[MyAuthorization()]
public ActionResult Create()
{
    return View();
}

 

Now let's get back to not using the standard role provider. In the save action of your forms authentication page, create a custom login ticket like this:

// Create forms auth ticket.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                1, // Ticket version
                "testUser", // Username associated with ticket
                DateTime.Now, // Date/time issued
                DateTime.Now.AddMinutes(30), // Date/time to expire
                false, // "true" for a persistent user cookie
                "Everyone|role2", // User-data, in this case the roles
                FormsAuthentication.FormsCookiePath);// Path cookie valid for


            // Encrypt the cookie using the machine key for secure transport
            string hash = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = new HttpCookie(
               FormsAuthentication.FormsCookieName, // Name of auth cookie
               hash); // Hashed ticket

            // Add the cookie to the list for outgoing response
            HttpContext.Response.Cookies.Add(cookie);

 

To be honest, we could even work without the FormsAuthentication ticket and just write the cookie ourselves, since we're also going to unwrap it later on.

 

In the Application_AuthenticateRequest event of global.asax, we are going to convert the authentication cookie back to a user:

 

if (HttpContext.Current.User != null)
            {
                if (HttpContext.Current.User.Identity.IsAuthenticated)
                {
                    if (HttpContext.Current.User.Identity is FormsIdentity)
                    {
                        FormsIdentity id =
                            (FormsIdentity)HttpContext.Current.User.Identity;
                        FormsAuthenticationTicket ticket = id.Ticket;

                        // Get the stored user-data, in this case, our roles
                        string userData = ticket.UserData;
                        string[] roles = userData.Split('|');
                        HttpContext.Current.User = new GenericPrincipal(id, roles);

                        Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(1031);
                        Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(1033);
                    }
                }
            }

 

You are pretty free to do here what you like, most of the time it will be some sort of backend access. Storing roles in the cookie as this example does is not really the way to go, better just keep your roles assignment on the server. Note, that the culture and ui culture are set at the end. This allows a culture to be set on a per user basis which is extemely helpful.

Tags: ,

ASP.NET MVC

Handing different submit actions in ASP.NET MVC

by Administrator 8. September 2010 13:14

When implementing forms in ASP.NET you may come across requirements where forms have multiple submit buttons triggering different actions (e.g. Save, Cancel, Delete, ...). Probably the most comfortable way to react to such actions is to have them hit different actions on your controller.

By default ASP.NET MVC looks at the name of the public methods on the controller class to match them up with the request. However this in itself is not really useful, because when dealing with forms you want to react differently to an HTTP POST rather than to an HTTP GET. You see this analogous in standard ASP.NET applications, where the Page_Load event checks, whether a postback happened. To make this possible, a set of attributes on methods was added that allows more logic.

[ActionName("Save")]

The actionname attribute overrides the standard lookup via method name. This makes sense in combination with the HTTP verbattributes like

[HttpGet]

Attributes sum up in their effect, so you could for instance designate one method to handle Save Http Post requests, while another handles Save Get requests. However this still does not do the job if you want to distinguish different types of posts. Submit buttons in forms have a value, which is submitted along with the post body. The value is also displayed as a text on the button. If you're doing a non multilingual application, you could go ahead and imnplement your own attribute that looks for the value of the submit. However at the point, where you get multilingual and the texts on the buttons are different for each language this is probably not the way to go.

Another problem with submit values is, that depending on which submit you use, you may also want a deviating client logic, e.g. no validation when hitting a cancel submit button. To solve this issue I did the following:

  • I wired up the submit buttons with an onclick handler to set a value on a hidden form field that indicates the kind of submit. This handler will depending on the type of submit in may case deactivate client-side form validation.
  • I created a filter attribute, that inspects this hidden field if it was posted.

public class OperationTypeAttribute : ActionMethodSelectorAttribute
{
        public OperationTypeAttribute(OperationType operationType)
        {
            OperationType = operationType;
        }

        public virtual OperationType OperationType
        {
            get;
            protected set;
        }


        public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
        {
            if (controllerContext.HttpContext.Request.RequestType.Equals("get", StringComparison.OrdinalIgnoreCase))
            {
                return OperationType == Project.Controller.OperationType.None;
            }
            else
            {
                string operationType = controllerContext.HttpContext.Request.Form["_OperationType"];

                return OperationType.ToString().Equals(operationType, StringComparison.OrdinalIgnoreCase);
            }
        }

}

OperationType is just an enumeration. The type none indicates, that no operation type is available, which is the case for an HTTP get. No I can designate methods on the controller using this attribute.

[OperationType(OperationType.Cancel)]

public ActionResult Detail_Cancel(Project.Models.CompanyInfo companyInfo);

Using this attribute makes filters on the HTTP verb obsolete.

Tags: , ,

ASP.NET MVC

Dependency Injection with ASP.NET MVC

by Administrator 7. September 2010 08:39

Perhaps something you should have in place for any bigger OO projects ist dependency injection. This allows an easy management of component interactions and introduces a great flexibility and awareness of too closely coupled components.

In my first project with dependency injection Spring.NET did the job. This framework offers so much more than pure dependency injection and it is absolutely great. However for this project I decided to search for a smaller more focuses library and came to use StructureMap. StructureMap is out there for a long time and appears still to recieve some maintenance. It's fast and easy to get a grasp on. However configuration and error handling appears to be quite flaky. However for now I guess I'll stick with it. I used an xml configuration file that expresses bindings. To wire up dependencies I chose constructor injection. Fortunately ASP.NET MVC plays really well with DI. 

I'm sorry about the code formatting, but BlogEngine seems to suck pretty bad at c#.

To get to controllers via dependency injection, you can register your own controller factory. A good place to register your controller factory is the Application_Start event in global.asax.

// Register DI aware controller factory.
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

The controller factory just implements two methods, one to build up a controller and one to tear it down:

public IController CreateController(RequestContext requestContext, string controllerName)
{

  // Build the name of the class by appending "Controller" to the controller name.
string controllerClassName = string.Format(   
CultureInfo.InvariantCulture,  
"{0}Controller",
    controllerName);
  return ObjectFactory.GetObjectInstance(controllerName)
}


In my case I had a dictionary that maps controller names to classes implementing the controller, I left that out to keep the code short.

public virtual void ReleaseController(IController controller)
{
// If the controller implements IDisposable, invoke the dispose method.
IDisposable disposableController = controller as IDisposable;

if (disposableController != null)
{
disposableController.Dispose();
}
}


When relasing a controller, I check whether it implements IDisposable and call Dispose if it does.

If you want to dwelve into ASP.NET MVC, a good starting point is Manning ASP.NET MVC in action. I learned a lot from this book. It's geared toward practice and nothing else and gives you a good startting point.

Tags: , ,

ASP.NET MVC

About the author

for comments and suggestions contact:

 

Month List