Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize alternate property names from form in POST

I am creating a callback endpoint for a third party API to hit. The caller will POST multipart form data to it.

Something like this:

public SomeApiController : ApiController {
  public AModel Post(AModel input) {
    return input; //for demonstration
  }
}

Some of the fields it will post have dashes in the name, which cannot be an actual .NET property name. So, I used [DataContract] and [DataMember(name="blah")] to define serialization rules.

Model:

//input model class
[DataContract]
public class AModel {
  [DataMember]
  public string NormalProperty {get; set;} //value set appropriately
  [DataMember(Name="abnormal-property")]
  public string AbnormalProperty {get; set;} //always null (not serializing)
}

With standard XML and JSON posts, this works fine. Normal and AbnormalProperty are set and I can carry about my business.

However, with any variant of form data (form-data, multiplart/form-data, x-urlencoded-form-data, AbnormalProperty doesn't properly deserialize into the model, and will always be null.

Is there a directive I'm missing or something?

like image 258
tonymke Avatar asked Oct 18 '14 14:10

tonymke


2 Answers

I have tried your example, and my conclusion is that the DefaultModelBinder in ASP.NET MVC does not support that naming of POST variables.

An obvious solution is not to use the dash in your names.

If that is not an option, then you can implement your own model binder for that specific model to handle the abnormal names you are sending to your MVC controller. Here is an example of a custom model binder:

public class AModelDataBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(AModel))
        {
            var request = controllerContext.HttpContext.Request;

            string normal = request.Form.Get("normalproperty");
            string abnormal = request.Form.Get("abnormal-property");

            return new AModel
            {
                NormalProperty = normal,
                AbnormalProperty = abnormal
            };
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

Then you would have to register this custom binder in Global.asax:

ModelBinders.Binders.Add(typeof(AModel), new AModelDataBinder());

And finally you can use the custom binder in your controller:

[HttpPost]
public ActionResult Index([ModelBinder(typeof(AModelDataBinder))]AModel input)
{
    // Handle POST

    return View();
}
like image 134
Faris Zacina Avatar answered Oct 11 '22 13:10

Faris Zacina


I think the main issue is with DataContract it expects raw data like XML. What you are trying to POST is HTML.

Types Supported by the Data Contract Serializer

like image 30
beautifulcoder Avatar answered Oct 11 '22 13:10

beautifulcoder