Contents tagged with MVC

  • Implementing resource oriented controllers in ASP.NET MVC

    One common problem with the naming convention and default routing mechanism in ASP.NET MVC is that we tend to group actions in a controller for sharing an URL space.  This basically leads to complex controllers with a lot of unrelated methods that break the SOLID principles.  Too many responsibilities in a simple class affects maintainability in the long run and causes secondary effects that complicates unit testing. For example, we usually end up with class constructors that receives too many dependencies as it is discussed here in SO.

    Read more...

  • The “Liike” project. Mobile Web guidance from Microsoft P&P

    Microsoft Patterns & Practices has recently started a new project whose codename is “Liike” (pronounced as LEEE-keh) for delivering guidance and a reference application in the mobile web space. As many of the recent initiatives started by different teams in Microsoft, this project will also be hosted in GitHub under http://liike.github.com/. All the artifacts, patterns and code generated during the project will be shared as part of that project.

    Read more...

  • Developing RESTful services with JSON and POX support in the ASP.NET MVC

    Many of the features available out of the box today in the ASP.NET MVC framework are only intended to develop web applications using REST principles. There is not support for accepting incoming messages encoded as JSON or plain old XML (POX), or even support for returning POX from a controller action. Only form-urlencoded data is accepted by default for incoming messages, and JSON/HTML (with support of the view engines) for outgoing messages in controller actions.

    However, thanks to the different extensibility points that the MVC provides for hooking up custom code, supporting different scenarios for RESTful services tend to be something really easy to implement.

    In this framework, we basically have two extensibility points that deserve some attention, Action Filters and Action Results.

    Action filters intercept messages before they are dispatched to the controller action (or operation), and just after the operation returns a result. They are basically equivalent to the Dispatch Message Interceptors in WCF, or the new Message Interceptors in the WCF REST Starter kit (although they work more at a deeper level in the WCF processing pipeline).

    Action results know how to serialize and write an object (the controller action result) into the response stream. Since they also have access to the Response object, additional work can be done there to manipulate some response settings or add output headers.

    The framework also support Model Binders, which basically knows how to create an object representing the model expected by the controller action from some scalar values. Those scalar values are parsed from the incoming message (encoded as form-urlencoded), and then passed to the binder. However, they do not seem to add any value for implementing RESTful services with support for JSON or XML.

    Omar Al Zabir has already written an nice post on how to implement RESTful services with the ASP.NET MVC that speak JSON and XML using action filters and action results.

    ATOM and other syndication formats can also be handled as XML. For this, the Web Programming Model in WCF comes with a couple of classes, Rss20FeedFormatter and Atom10FeedFormator, which are Data Contracts and also IXmlSerializable classes. Therefore, if your operation returns an instance of any of these classes, the filters created by Omar would address this scenario as well. Regarding Conditional get support, you will have to implement it in the action itself or a custom filter. (You will have to do the same thing if you decide to go with the WCF Web Programming Model).

    Caching is another feature that you might want to use at the moment of developing RESTful services. Fortunately, the MVC also comes with an special action filter “OutputCache” that was built on top the ASP.NET cache, so it provides the same caching capabilities that you may use for normal ASP.NET pages.

    Read more...

  • Running a partial SSL website with ASP.NET MVC

    Keith Brown has just released a helper class (Based on an original implementation made by Dominick Baier) with very useful methods for mixing Http and Https in a regular asp.net application. Before jumping in this post, make sure to read his post (And Dominick's) to understand all the problems you may have to deal with when implementing a partial SSL website.

    Running a partial SSL website in ASP.NET MVC is not much different, however, in MVC, we can leverage the existing and powerful routing mechanism to implement similar features.

    Switching to SSL through an ASP.NET Module

    This module  basically inspects the URL and does a redirect based on some configuration where you specify routes that should be SSL protected.

    public void ProcessRequest(HttpContext context)

    {

        if(Authentication.IsSslRequired() && context.Request.HttpMethod.Equals("get", StringComparison.OrdinalIgnoreCase))

        {

            var data = RouteTable.Routes.GetRouteData(new HttpContextWrapper(context));

            if (data != null)

            {

                if (!context.Request.IsSecureConnection)

                {

                    if(data.DataTokens["isSecure"] != null && (bool)data.DataTokens["isSecure"])

                    {

                        //Do redirect to https

                        var secureUrl = context.Request.Url.ToString().ToSslUrl();

                        context.Response.Redirect(secureUrl, true);

                    }

                }

                else

                {

                    if (data.DataTokens["isSecure"] == null || !((bool)data.DataTokens["isSecure"]))

                    {

                        //Do redirect to http

                        var unsecureUrl = context.Request.Url.ToString().ToUnsecureUrl();

                        context.Response.Redirect(unsecureUrl, true);

                    }

                }

            }

        }

    }

    As you can see in the code above, the module checks whether the page should be ssl protected using a custom data token (IsSecure) that was previously configured for the route, and afterwards, it redirects the request according to that setting. For instance, if the route requires to be the secure (IsSecure = true), and the request was actually made through http, the module will redirect the request to https.

    The absolute URLs are built using some extensions methods (ToSslUrl and ToUnsecureUrl) that I will show later in this post.

    Authentication.IsSslRequired is just an configuration setting that we can use to skip all these checks during development.

    public class Authentication

    {

        public static bool IsSslRequired()

        {

            var setting = ConfigurationManager.AppSettings["RequireSSL"];

            if (setting != null)

            {

                return bool.Parse(setting);

            }

     

            return false;

        }

    }

     

    <appSettings>

      <add key="RequireSSL" value="True"/>

    </appSettings>

    The code for setting the custom data token in the MVC route looks as follow,

    routes.MapRoute(

        "MyAccount/PasswordChange",

        "MyAccount/PasswordChange",

        new { controller = "Accounts", action = "PasswordChange" }

    ).DataTokens = new RouteValueDictionary(new { isSecure = true });

     

    Extension methods for generating absolute URLs

    As I showed before in the ASP.NET Module, two extensions methods were used to generate absolute URLs. I just based their implementation on some code originally written by Troy Goode in this post.

    /// <summary>

    /// Provides helper extensions for turning strings into fully-qualified and SSL-enabled Urls.

    /// </summary>

    public static class UrlStringExtensions

    {

        /// <summary>

        /// Takes a relative or absolute url and returns the fully-qualified url path.

        /// </summary>

        /// <param name="text">The url to make fully-qualified. Ex: Home/About</param>

        /// <returns>The absolute url plus protocol, server, & port. Ex: http://localhost:1234/Home/About</returns>

        public static string ToFullyQualifiedUrl( this string text )

        {

            var oldUrl = text;

            var oldUrlArray = ( oldUrl.Contains( "?" ) ? oldUrl.Split( '?' ) : new[]{ oldUrl, "" } );

     

            var requestUri = HttpContext.Current.Request.Url;

            var localPathAndQuery = requestUri.LocalPath + requestUri.Query;

            var urlBase = requestUri.AbsoluteUri.Substring( 0, requestUri.AbsoluteUri.Length - localPathAndQuery.Length );

     

            var newUrl = VirtualPathUtility.ToAbsolute( oldUrlArray[0] );

            if( !string.IsNullOrEmpty( oldUrlArray[1] ) )

                newUrl += "?" + oldUrlArray[1];

     

            return urlBase + newUrl;

        }

     

        /// <summary>

        /// Looks for Html links in the passed string and turns each relative or absolute url and returns the fully-qualified url path.

        /// </summary>

        /// <param name="text">The url to make fully-qualified. Ex: <a href="Home/About">Blah</a></param>

        /// <returns>The absolute url plus protocol, server, & port. Ex: <a href="http://localhost:1234/Home/About">Blah</a></returns>

        public static string ToFullyQualifiedLink( this string text )

        {

            var regex = new Regex(

                "(?<Before><a.*href=\")(?!http)(?<Url>.*?)(?<After>\".+>)",

                RegexOptions.Multiline | RegexOptions.IgnoreCase

                );

     

            return regex.Replace( text, ( Match m ) =>

                                        m.Groups["Before"].Value +

                                        ToFullyQualifiedUrl( m.Groups["Url"].Value ) +

                                        m.Groups["After"].Value

                );

        }

     

        /// <summary>

        /// Takes a relative or absolute url and returns the fully-qualified url path using the Https protocol.

        /// </summary>

        /// <param name="text">The url to make fully-qualified. Ex: Home/About</param>

        /// <returns>The absolute url plus server, & port using the Https protocol. Ex: https://localhost:1234/Home/About</returns>

        public static string ToSslUrl( this string text )

        {

            if (IsSslRequired())

            {

                string absoluteUrl = null;

                if (text.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || text.StartsWith("https://", StringComparison.OrdinalIgnoreCase))

                    absoluteUrl = text;

                else

                    absoluteUrl = ToFullyQualifiedUrl(text);

     

                return absoluteUrl.Replace("http:", "https:");

            }

            else

            {

                return text;

            }

        }

     

        /// <summary>

        /// Takes a relative or absolute url and returns the fully-qualified url path using the Http protocol.

        /// </summary>

        /// <param name="text">The url to make fully-qualified. Ex: Home/About</param>

        /// <returns>The absolute url plus server, & port using the Http protocol. Ex: http://localhost:1234/Home/About</returns>

        public static string ToUnsecureUrl(this string text)

        {

            string absoluteUrl = null;

            if (text.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || text.StartsWith("https://", StringComparison.OrdinalIgnoreCase))

                absoluteUrl = text;

            else

                absoluteUrl = ToFullyQualifiedUrl(text);

     

            return absoluteUrl.Replace("https:", "http:");

        }

     

        /// <summary>

        /// Looks for Html links in the passed string and turns each relative or absolute url into a fully-qualified url path using the Https protocol.

        /// </summary>

        /// <param name="text">The url to make fully-qualified. Ex: <a href="Home/About">Blah</a></param>

        /// <returns>The absolute url plus server, & port using the Https protocol. Ex: <a href="https://localhost:1234/Home/About">Blah</a></returns>

        public static string ToSslLink( this string text )

        {

            if (IsSslRequired())

            {

                return ToFullyQualifiedLink(text).Replace("http:", "https:");

            }

            else

            {

                return ToFullyQualifiedLink(text);

            }

        }

     

        private static bool IsSslRequired()

        {

            return Authentication.IsSslRequired();

        }

    }


    They can be used from a view as well to generate links with complete Urls,

    <a href='<% =Url.Action("PasswordChange", "Accounts").ToSslUrl() %>'>Change your password</a>

    Gettting an absolute URL within a controller

    For some scenarios, we might need to redirect the user from a secure route to a regular route or viceversa within a controller. In those cases, we should have a way to generate a complete URL from a controller method and used it later with a RedirectResult (This is also useful when you want to include a link to a web page in an email sent by your website).

    For instance, it would be very helpful to have something like this,

    return new RedirectResult(this.FullActionUrl<MyController>(c => c.SecureMethod(), "https"));

    Where "FullActionUrl" is an extension method for the Controller class. In addition to the controller method we want to use to get the absolute route ("SecureMethod"), we can also specify the scheme to be used with that route.

    The code for doing that is shown bellow (They are part of the .NETfx project, http://code.google.com/p/netfx/)

    /// <summary>

    /// Returns the full URL for performing an invocation to an action based

    /// on an expression representing an invocation to a controller method

    /// that may include arguments.

    /// </summary>

    /// <typeparam name="T">Type of the controller to call to. Can be omitted as it can be inferred from the action type.</typeparam>

    /// <param name="controller">The controller performing the call.</param>

    /// <param name="action">The action containing the call.</param>

    public static string FullActionUrl<T>(this Controller controller, Expression<Action<T>> action, string scheme)

        where T : Controller

    {

        string host = controller.HttpContext.Request.Url.Authority;

        string virtualPath = ActionUrl(controller, action);

     

        return string.Format("{0}://{1}{2}", scheme, host, virtualPath);

    }

     

    /// <summary>

    /// Returns the URL for performing an invokation to an action based

    /// on an expression representing an invocation to a controller method

    /// that may include arguments.

    /// </summary>

    /// <typeparam name="T">Type of the controller to call to. Can be omitted as it can be inferred from the action type.</typeparam>

    /// <param name="controller">The controller performing the call.</param>

    /// <param name="action">The action containing the call.</param>

    public static string ActionUrl<T>(this ControllerBase controller, Expression<Action<T>> action)

        where T : Controller

    {

        var call = ControllerExpression.GetMethodCall<T>(action);

     

        string actionName = call.Method.Name;

        string controllerName = ControllerExpression.GetControllerName<T>();

     

        var values = LinkBuilder.BuildParameterValuesFromExpression(call);

        values.Add("action", actionName);

        values.Add("controller", controllerName);

     

        var vpd = RouteTable.Routes.GetVirtualPath(controller.ControllerContext, values);

        string target = null;

        if (vpd != null)

        {

            target = vpd.VirtualPath;

        }

     

        return target;

    }

    The complete code is available to download from here

    Read more...

  • Implementing an identity provider and relying party with Zermatt and ASP.NET MVC

    Zermatt is the framework recently released by Microsoft to develop claim-aware applications. You can find some announcements here and here.

    This framework supports the WS-Federation active and passive profiles. This last one was initially designed with an unique purpose in mind, allow the integration of "dumb clients" into the identity metasystem. As "dumb clients", I am talking about clients like web browsers that do not have the ability to handle cryptographic material.

    All the magic is done through some consecutive Http redirects, and today we will see how develop an identity provider and a relying party web (with ASP.NET MVC) that are involved in the whole process.

    The identity provider is based on the quickstart that is automatically generated in Visual Studio when you create a new MVC web application. This quickstart uses FormsAuthentication to authenticate the application users and also provides an Account controller (that internally uses ASP.NET Membership) to manage all those users. In order to integrate Zermatt in this application, I added a new controller STSController that knows to process messages for getting issue tokens with the user's claims.

    For the relying party, Zermatt provides some web controls to authenticate the user against the identity provider using the passive profile. Unfortunately, for the simple fact that ASP.NET MVC does not support controls with view state, we can not use them here. As workaround, I created a couple of extensions methods that generate the Urls for sending the corresponding messages to the identity provider (Login and Logout).

    public static class LoginUrlExtensions

    {

       public static string LoginUrl(this UrlHelper helper, string actionName, string controllerName, string stsUrl)

       {

           string host = helper.ViewContext.HttpContext.Request.Url.Authority;

           string schema = helper.ViewContext.HttpContext.Request.Url.Scheme;

     

           string realm = string.Format("{0}://{1}", schema, host);

           string reply = helper.Action(actionName, controllerName).Substring(1);

     

           return string.Format("{0}?wa=wsignin1.0&wtrealm={1}&wreply={2}&wctx=rm=0&id=FederatedPassiveSignIn1&wct={3}",

              stsUrl, realm, reply, XmlConvert.ToString(DateTime.Now));

       }

     

       public static string LogoutUrl(this UrlHelper helper, string actionName, string controllerName, string stsUrl)

       {

           string host = helper.ViewContext.HttpContext.Request.Url.Authority;

           string schema = helper.ViewContext.HttpContext.Request.Url.Scheme;

     

           string realm = string.Format("{0}://{1}", schema, host);

           string reply = string.Format("{0}{1}", realm, helper.Action(actionName, controllerName));

     

           return string.Format("{0}?wa=wsignout1.0&wreply={1}", stsUrl, reply);

       }

    }

    The "actionName" and "controllerName" are just used to generate the reply address where the user must be redirect after being authenticated in the identity provider. These extension methods can be used in the view as follow,

    <a href="<%=Url.LoginUrl("Login", "Home", "localhost://STS")%>">Login</a>

    We also need a method in the relying party to parse the RRST message and generate a cookie with the user credentials and claims.

     

    public interface IFederatedAuthentication

    {

       IClaimsPrincipal Authenticate();

    }

     

    public class FederatedAuthentication : IFederatedAuthentication

    {

         private string logoutUrl;

     

         public FederatedAuthentication(string logoutUrl)

         {

             this.logoutUrl = logoutUrl;

         }

     

         public IClaimsPrincipal Authenticate()

         {

             string securityTokenXml = FederatedAuthenticationModule.Current.GetXmlTokenFromPassiveSignInResponse(System.Web.HttpContext.Current.Request, null);

     

             FederatedAuthenticationModule current = FederatedAuthenticationModule.Current;

     

             SecurityToken token = null;

             IClaimsPrincipal authContext = current.AuthenticateUser(securityTokenXml, out token);

     

             TicketGenerationContext context = new TicketGenerationContext(authContext, false, logoutUrl, typeof(SignInControl).Name);

             current.IssueTicket(context);

     

             return authContext;

         }

    }

     

    As you can see in the code above, the Zermatt module (FederatedAuthenticationModule) that parses the response message is tied to the Request object, something that we do not have direct access from a MVC controller (Well, it is bad practice if we want to test our code). That's the reason I decided to put all that code in a pluggin that can be injected later in the controller.

    The complete solution is available to download from this location. Any feedback would be great!!. Enjoy!!.

    Read more...

  • Dependency injection made easy for the ASP.NET MVC

    I decided to write this post to show how cool is Autofac for doing dependency injection in the ASP.NET MVC framework. Autofac, for me the Moq stepbrother  in the dependency injection arena because of its very-easy-to-use fluent interface and nice support of lambda expressions, comes with a built-in ASP.NET module to automatically intercept the creation of the controllers and pass the required dependencies to them, the only thing a programmer has to do is to provide instances of those dependencies or expressions to build them.

    Well, it is time to see Autofac in action with a practical example. If you have the chance to use the MVC preview 4, you may notice that it comes with a new controller "Account" to manage the website membership. This controller receives two dependencies in the constructor,

    public AccountController(IFormsAuthentication formsAuth, MembershipProvider provider)

    {

      FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

      Provider = provider ?? Membership.Provider;

    }

     

    public IFormsAuthentication FormsAuth

    {

      get;

      private set;

    }

     

    public MembershipProvider Provider

    {

      get;

      private set;

    }

    If those dependencies are not provided, it creates a default implementation of "FormsAuthenticationWrapper" and use the Membership singleton instance. Ok, let's make some minor changes to this controller so we always assume that those instances must be provided by the caller code (It will be actually responsibility of the DI container).

    public AccountController(IFormsAuthentication formsAuth, MembershipProvider provider)

    {

      FormsAuth = formsAuth;

      Provider = provider;

    }

    We now have to initialize a container to instruct Autofac about how to initialize or get instances of those classes. This can be done in the global.asax file,

    static IContainerProvider containerProvider;

     

    protected void Application_Start()

    {

       RegisterRoutes(RouteTable.Routes);

     

       var builder = new ContainerBuilder();

     

       // Automatically register all controllers in the current assembly.

       builder.RegisterModule(new AutofacControllerModule(Assembly.GetExecutingAssembly()));

     

       builder.Register<MembershipProvider>(container => Membership.Provider).ExternallyOwned();

       builder.Register<FormsAuthenticationWrapper>().As<IFormsAuthentication>().FactoryScoped();

     

       containerProvider = new ContainerProvider(builder.Build());

     

       // Hook MVC factory.

       ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(containerProvider));

    }

    There are some lines in the code above that deserve special attention, so let's discuss them in details:

    1.

    // Automatically register all controllers in the current assembly.

    builder.RegisterModule(new AutofacControllerModule(Assembly.GetExecutingAssembly()));

    This line basically discovers and registers all the controllers within the current assembly (The website itself) into the DI container.

    2.

    builder.Register<MembershipProvider>(container => Membership.Provider).ExternallyOwned();

    builder.Register<FormsAuthenticationWrapper>().As<IFormsAuthentication>().FactoryScoped();

    The dependencies are registered in the container builder (The one that later knows how to create instances of the dependencies). The Register method optionally receives an lambda expression that will be used later to create or get the dependency instance, it could be considered a sort of lazy class construction. The container can also be used in the expressions to resolve other dependencies, for example,

    builder.Register<MessagingService>(c => new MessagingService(c.Resolve<IMessageRepository>).As<IMessagingService>();

    Another important aspect in the initialization is the scope, which basically controls the dependency lifetime. In the code above I used two scopes, ExternallyOwned (The instance is managed by the application) and FactoryScoped (A new instance is created for every dependency resolution, very useful for instances that must be used and disposed just after, like the DataContext in Linq to SQL). Other possible scopes could be ContainerScoped (An instance per container) or Singleton (An instance shared between all containers).

    3.

    containerProvider = new ContainerProvider(builder.Build());

     

    // Hook MVC factory.

    ControllerBuilder.Current.SetControllerFactory(new AutofacControllerFactory(containerProvider));

    The container provider is created, and the controller factory implementation provided by Autofac is set for the current application.

    As you can see, most of the plumbing code is already provided by Autofac, just a couple of lines were needed to start using DI in the MVC framework.

    The code sample is available to download here

    Read more...

  • Combining JQuery Validation with ASP.NET MVC

    One of the most nicest things about JQuery - in addition to the powerful mechanism it provides to manipulate the HTML DOM - is the great number of very useful plugins available out there.

    JQuery Validation is one of my favorites, and today we will see how this plugin can be used with the MVC framework to validate all the inputs in a form before it is submitted to the controller.

    This plugin supports the concept of "validation rule", a validation that has to be performed to an input field. For instance, "The field is required", "The field should have at least N characters", or "This field has to be a valid email", many of them are the same you can find in the ASP.NET validators. (These validators do not work with the MVC framework because they are tied to the ASP.NET Viewstate). Of course, new rules can also be created for performing custom validations specific to an application, some examples of this are also available in the plugin's website.

    A rule can be applied to an input field in two ways:

    1. Declarative, the rule is specified in the input field by means of the class attribute:

    <input name="email" id="email" maxlength="60" class="required email" type="text"/>

    As you can see, two rules were specified in the class attribute, "Required" and "Email", which means that two validations have to be performed for this field. Many rules can be applied to the same field, they only have to be separated by an space.

    2. Imperative in code, the rule is specified in an script:

    <script type="text/javascript">

    $(document).ready(function(){

      $("#form-sign-up").validate( {

        rules: {

          email: {

            required: true,

            email: true

        },

        messages: {

          email: {

            required: "Please provide an email",

            email: "Please provide a valid email"

         } });

    });

    </script>

    The validation was attached to the input field "email" in the form "form-sign-up". The message displayed when a validation fails for an specific field can also be customized using the "messages" section in the script. (This is optional, the plugin already comes with a set of pre-defined error messages)

    And finally, one of the most interesting validation rules you can find there is "remote", which performs a remote validation using an Ajax endpoint. At this point we can use an MVC controller method to perform an specific validation, for instance to see if a login name is still available to be used.

    <script type="text/javascript">

    $(document).ready(function(){

    $("#form-sign-up").validate( {

      rules: {

        login: {

          required: true,

          remote: '<%=Url.Action("IsLoginAvailable", "Accounts") %>'

       }

      },

      messages: {

        login: {

         required: "Please provide an alias",

         remote: jQuery.format("{0} is already in use")

       }

      } });

    });

    </script>

    The only requirement for the controller is that it must be return Json with the result of the validation. This can be easily done with MVC,

    public JsonResult IsLoginAvailable(string login)

    {

        //TODO: Do the validation

        JsonResult result = new JsonResult();

        if (login == "cibrax")

          result.Data = false;

        else

          result.Data = true;

     

        return result;

    }

    In the example above, if "cibrax" is entered as login name, the validation will fail and the user will see an error message.

    The styles for the error messages can also be customized with the following rules,

    label.error {

    display: block;

    color: red;

    font-style: italic;

    font-weight: normal;

    }

    input.error {

    border: 2px solid red;

    }

    td.field input.error, td.field select.error, tr.errorRow td.field input,tr.errorRow td.field select {

    border: 2px solid red;

    background-color: #FFFFD5;

    margin: 0px;

    color: red;

    }

    As we have discussed here, JQuery validation is a great tool that we all should consider at the moment to validate data in the ASP.NET MVC framework.

    A complete example with different validations can be downloaded from this location.

    Read more...