Removing errors from ModelState in MVC

I wouldn’t normally try to override MVC’s own validation on textboxes etc but occasionally it can be useful. All the things I have seen so far on the Web are pretty messy – turning the ModelState into a dictionary and then iterating through it – and then just removing all the errors associated with that screen control regardless of what the error is. Not very subtle and a bit hacky.

The code below shows a way of doing this in the (slightly contrived but simple) situation where you have a view model with a strongly typed non-nullable DateTime tied to a textbox. This will of course throw an error automatically when trying to submit a blank in the textbox – which is great most of the time. However in a particular context you might want to allow it. Instead of making the DateTime nullable in the view model, and then manually testing for null you could also check for the error in the ModelState and then remove it. Here is how:

public ActionResult Save(MyViewModel model, string btnSave, string btnCancel)
{
       ModelState val;
       if (ModelState.TryGetValue("MyDate", out val) == true)
       {
              if (val.Value.AttemptedValue == "") // Test for the string you are going to allow here              
              {
                        ModelState.Remove(new KeyValuePair<string, ModelState>("MyDate", val));
                        model.MyDate = null; // Set your property to whatever your override is here
              }
       }

      .....
}
 

Obviously the example is a little bit contrived, but the point is that you can use the AttemptedValue property to check for specific entered values – which is useful if you only want to check for a particular value. Also – the TryGetValue method is very useful too, no converting to dictionaries and iterating needed!

Advertisements

MVC – Getting User Roles From Multiple Sources (register and resolve arrays of dependencis using the fluent api)

In the last post I talked about encapsulating the authorisation and user credentials (i.e IPrincipal) logic in a separate, re-usable DLL (known as AuthServices).

Part 1 of that post discussed the DLL contents in detail. Part 2 focused upon using that DLL in an MVC application.

This post follows up on “Part 2” specifically adding a user’s roles to the UserData objet prior to serialisation, on-route to becoming the auth cookie.

The code sample that I gave for using the AuthServices DLL is repeated below:

_authenticationService.Authenticate(userNameString, password);
if (_authenticationService.Result.Authenticated)
{
       _currentUserData = _authenticationService.Result.CurrentUserData;
       _currentUserData.Roles = GetRolesForUser(userName);//THE SUBJECT OF THIS POST
       _cookieManager.CreateUserCookie(userName, _currentUserData);
}

This post explores in more detail what lies behind the GetRolesForUser(string userName) method and how this can utilise more than one provider of roles.

Why bother?

The organisation in which I work is big. We have thousands of staff and many thousands more students. Applications written for an organisation of this size usually need to access different sources of data to provide a user’s roles relevant to the specific application. In projects like this you can’t easily use the standard RoleProvider stuff in a config file.

The Answer – Multiple Role Providers

To implement multiple roles I inject (in an IOC stylee) into my login service the interface IRolesMgr. IRolesMgr exposes the following:

public interface IRolesMgr
    {
        List GetAllRolesForUser(string userName);
    }

The interesting part is in the constructor of the implementation.

public class RolesMgr: IRolesMgr
    {
        private IRoleMgrComponent[] _roleManagers;

        public RolesMgr(IRoleMgrComponent[] roleManagers)
        {
            _roleManagers = roleManagers;
        }

        public List GetAllRolesForUser(string userName)
        {
            List roles = new List();
            foreach (var mgr in _roleManagers)
            {
                roles.AddRange(mgr.GetRolesForUser(userName));
            }
        }
    }

As can be seen the constructor has a dependency on an array of IRoleMgrComponents each of which will contain the access logic needed to identify a user’s roles from a different source.
Each IRoleMgrComponent implements the following:

public interface IRoleMgrComponent
    {
        List GetRolesForUser(string userName);
    }

That’s all very good, but the trick is getting the IOC container, in this case, Castle Windsor, to instantiate the appropriate implementations of IRoleMgrComponent in the roleManagers array.

This is done in the Component Registrar class used to register components to Castle by using the “ServiceOveride” method (more details of this can be seen on Mike Hadlow’s post – which was the original inspiration for the castle registration code – thanks Mike!). In effect this allows you to register and resolve arrays of dependencis using the fluent api.

container.Register(
                Component.For()
                    .ImplementedBy()
                    .ServiceOverrides(
                        ServiceOverride.ForKey("roleManagers").Eq(
                            "HumsAuthDbRoleManager",
                            "StudentAuthRoleMgr"
                        )
                    ),
                AllTypes
                    .FromAssemblyNamed("ApplicationServices")
                    .BasedOn()
                        .WithService.FromInterface(typeof(IRoleMgrComponent))
                        .Configure(c => c.Named(c.Implementation.Name))
                );

Once you have overriden this specific component you can continue to register all the other components in that assembly in the normal way, say:

container.Register(
                AllTypes.Pick()
                .FromAssemblyNamed("ApplicationServices")
                .WithService.FirstInterface());

Conclusion

Implementing RolesMgr(IRoleMgrComponent[]) in conjunction with the AuthServices assembly talked about in the last post, means that for any given new project I will only have to write minimal code yet benefit from User Credential information that:
a) Has the execution logic encapsulated in an (extensible) AuthServices library
b) Can uitilise dependency injection to configure how where and how the roles data comes from in the credential information.

Creating a resusable Authorisation/ User Principal library for MVC projects

Having been using SharpArchitecture/ MVC for a number of recent projects, I’ve finally made the effort to extract some common service features into a separate reusable project (with unit tests of course!). This is very much inkeeping with DRY principles and should shorten the time to (re)-implement common processes in new projects.

The project – AuthUserServices provides several useful interface/implementations that can be used in any (MVC/ or Non-MVC) .NET project. It aint rocket science but provides a number of neat and unit tested resources around Authorisation and GenericPrinicpal.

Part 1 – The AuthServices DLL

The IAuthenticationService

This interface exposes two methods:

void Authenticate(string userName, string password)// Authenticates against a user directory
void FindUser(string userName)// Ascertains whether a user is contained in a user directory

And an AuthenticationResult propterty…

AuthenticationResult Result { get; }

… which is a struct containing result information supplied from “Authenticate” or “FindUser”.

The current implementation(s) of this interface are for LDAP and CAS. Our MVC projects implement dependency injection using Castle Windsor. It is therefore fairly trivial to choose the IAutheniticationService implementation in the component register (specific examples to follow).

AuthenticationResult

The AuthenticationResult struct exposes the following properties:

public bool Authenticated {get;}// bool describing whether a user is authenticated
public string ConnectionMessage {get;}// any message that comes from connecting with/ or communicating with a user directory
public string SearchString {get;} // the string used to search the user directory, i.e. the username
public IUserData UserData {get;}// An object containing user details gleaned from searching the user directory

IUserData

IUserData exposes the following properties:

string Email { get; }
string FName { get; }
string SomeOtherProperty { get; }
List Roles { get; set; }
string SName { get; }
string ToString();

In the AuthServices project there is only one implementation of this interface (cunningly) called UserData. I implemented this as an interface so that it is possible to provide other implementations in the future. For example the

ToString()

implementation is used to serialise the object for use in a cookie. It is possible that a developer may with to implement a different serialisation algorithm.

UserData

UserData object data is built from a directory search or authentication attempt. It has two constuctors.
The first is used to create the UserData from properties gleaned from the user directory

public UserData(string email, string fName, string sName, string someOtherProperty)

The second is used to deserialise a userDataString contained in the UserData property in an auth cookie (in effect the reverse of the

ToString()

implementation.

public UserData(string userDataString)

The UserData class encapsulates the logic involved in managing user data across the Authorisation –> Cookie serialisation/deserialisation –> Building the User Principal process.

ICurrentUserCookieMgr

The ICurrentUserCookieMgr interface doesn’t expose a huge amount of functionality.

void CreateUserCookie(string userName, IUserData userData);
bool HttpOnly { get; set; }
void RemoveUserCookie();

The current implementation implements FormsAuthentication. It is the only part of the service that doesn’t really have adequate unit tests due to it’s (necessary) reliance upon HttpContext and the Response therein. Still the implemenation encapsulates this functionaly and can easily be stubbed/ mocked in application unit tests.

IHumsPrincipal

The final item of the service is the IHumsPrincipal interface. This exposes the the UserData and UserName properties as well as the IIdentity and property and IsInRole method available in the standard MS IPrincipal interface.

IIdentity Identity { get; }
bool IsInRole(string role);
IUserData UserData { get; }
string UserName { get; }

Part 2 – Example Uses in an (MVC) app

Using AuthServices in the Authorisation logic of an application

I use the AuthServices implementation in a LoginService within an ApplicationServices project.
The LoginService has the following private members

private ICurrentUserMgr _userManager;
private IAuthenticationService _authenticationService;
private ICurrentUserCookieMgr _cookieManager;

You can then manage the whole cookie building/ roles setting process with only a few lines of code

_authenticationService.Authenticate(userNameString, password);
if (_authenticationService.Result.Authenticated)
{
       _currentUserData = _authenticationService.Result.CurrentUserData;
       _currentUserData.Roles = GetRolesForUser(userName);//Some logic to determine the roles (SEE NEXT BLOG POST ABOUT THIS)
       _cookieManager.CreateUserCookie(userName, _currentUserData);
}

Accessing User Info

Post authentication, developeres can use the implementations of IHumsPrincipal and IUserData in theĀ Application_OnAuthenticateRequest in the Global.asax file of their apps to expose UserData properties to the application. e.g.

FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userId = id.Ticket.Name;
IUserData uData = new UserData(id.Ticket.UserData);
HttpContext.Current.User = new HumsPrincipal(id.Name, uData, id);

You could then expose the IHumsPrincipal members in the application (such as a controller or application by casting the CurrentPrincipal to the IHumsPrincipal as follows:

IHumsPrincipal p = Thread.CurrentPrincipal as IHumsPrincipal;

Better still would be to encapsulate this cast behind an “ICurrentUserManager” interface to remove the dependency within controller/app service methods upon the Thread and therefore make such methods easy to unit test. For example:

public class CurrentUserMgr: ICurrentUserMgr
    {
        IHumsPrincipal _principal
        {
            get
            {
                try
                {
                     return Thread.CurrentPrincipal as HumsPrincipal;
                }
                catch
                {
                    return null;
                }
            }
        }

        public CurrentUserMgr()
        {

        }

        public bool IsStudent()
        {
            if (_principal == null)
                return false;
            else return _principal.IsInRole("student");
        }

        public bool IsSysAdmin()
        {
            if (_principal == null)
                return false;
            else return _principal.IsInRole("sysadmin");
        }

        public bool IsLoggedIn()
        {
            try
            {
                return _principal.Identity.IsAuthenticated;
            }
            catch
            {
                return false;
            }
        }
    }

Castle Wiring of AuthServices DLL in the Component Register

Finally, in an MVC, project you have to register AuthServices library in an MVC project.

container.Register(
     AllTypes.Pick()
     .FromAssemblyNamed("Humanities.Reusable.Components.AuthUserServices")
     .WithService.FirstInterface());

FileUpload control with UpdatePanel (WebForms)

The asp:FileUpload control rather irritatingly does not work within an UpdatePanel in ASP.NET Webforms. This is probably something to do with security (which always seems to be an issue with AJAX!).

To get round this problem you can of course take it out of the UpdatePanel and have it on a separate form, but that is not really that slick, and I expect the main reason you are trying to do this is for slickness!

The solution is to put the upload control and associated upload functionality on another aspx page, and then include the page within your form using an iframe with the frameborder property set to zero. Of course that is not perfect, as you will need to provide a separate button for uploading, which might be irritating to the user. On the other hand that also allows you to display things like photo uploads relatively easily and apparently seamlessly.

Your main problem will be giving the upload page the information about where to store the file/photo (if it associated with a specific data record). When updating a record this can be passed as a parameter to the page request. Adding a record is more tricky. In this case if you generate your data’s key prior to saving then no problem, but if you allow the database to do it after saving it is a problem, as you can’t pass it through to the upload page! In this scenario the best process flow might be not allow file uploads in insert mode – just ask the user to save the data record, then have the page automatically go into edit mode afterwards for photos.

It all feels a little bit hacky but sometimes that is just the way AJAX works!