developer747
developer747

Reputation: 15958

Manipulate Model Binding in MVC 4

This is easier to explain with an example. Suppose I have a person class

Public Person
{
string firstName;
string SocialSecurityNumber;
}

When some changes are made by the user in a web page, the Person object is posted back to a controller that accepts Person as the input parameter. The SocialSecurity number is encrypted. We have many pages that post back objects (Not Necessarily Person class) that have encrypted Social security as a parameter. Now I want to modify the model binding, so that if the posted object has SocialSecurityNumber as a property, it should be automatically decrypted. How can I do this?

Upvotes: 2

Views: 2256

Answers (2)

Mightymuke
Mightymuke

Reputation: 5144

You could use a custom model binder. Some examples:

This is an example of a simple one I've used before that you could modify for your needs:

public class FormatterModelBinder : DefaultModelBinder
{
    internal static string TrimValue([CanBeNull] string value, [CanBeNull] FormatAttribute formatter)
    {
        if (string.IsNullOrEmpty(value)) return value;
        return ((formatter == null) || formatter.Trim) ? value.Trim() : value;
    }

    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
        if ((propertyDescriptor != null) && (propertyDescriptor.PropertyType == typeof(string)))
        {
            var stringValue = value as string;
            var formatter = propertyDescriptor.Attributes.OfType<FormatAttribute>().FirstOrDefault();
            stringValue = TrimValue(stringValue, formatter);
            value = stringValue;
        }

        base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
    }
}

You could then create an attribute to decorate the property as required:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class FormatAttribute : Attribute
{
    public FormatAttribute()
    {
        Trim = true;
    }

    public bool Trim { get; set; }
}

This is "activated" by an attribute on the property in the ViewModel

Public Person
{
    string firstName;
    [Format(Trim = true)]
    string SocialSecurityNumber;
}

It should be fairly simple to modify this to allow for encryption.

Upvotes: 1

Travis J
Travis J

Reputation: 82337

Perhaps you should store it in its own class

public class Person
{
 public string firstName { get; set; }
 public SocialSecurityNumber SSN { get; set; }
}

public class SocialSecurityNumber
{
 public string SSN { get; set; }
}

Perhaps the class could have its own decrypt method as well.

public class SocialSecurityNumber
{
 public string SSN { get; set; }

 public string Decrypt()
 {
  //TODO: Decrypt SSN
  return decrypted ssn
 }
}

Now in your controller

[HttpPost]
public ActionResult PostedPerson (Person person)
{
 string PersonName = person.firstName;
 string SocialSecurityNumber = person.SSN.SSN;//or person.SSN.Decrypt();
 //TODO: decrypt SocialSecurity number
}

In the case where you are using FormCollection for model binding, then you would have to set some sort of flag or use an abstraction to mark that the field was encrypted

public class Person
{
 public string firstName { get; set; }
 public SocialSecurityNumber SSN { get; set; }
}

public class SocialSecurityNumber
{
 public string SSN { get; set; }
 public string Encrypted { get; set; }//set this to "EncryptedTrue" or something
                                      //similar in order to handle it in the post
}

And then with your form collection

[HttpPost]
public ActionResult PostedPerson (FormCollection fc)
{
 for( var val in fc )
 { 
  if( val is InnerList ){
  {
   if( val.Contains("EncryptedTrue") )
   {
    //then val.SSN would be an encryped social security number
   }
  }
 }
}

Upvotes: 1

Related Questions