0

I am writing Angular.js/ASP.NET application. I have defined this model:

public class Dealer : EntityBase
{
    ...
    public virtual List<DealerDefinedService> DealerDefinedServices { get; set; }
    public virtual List<DealerDefinedServicesDiscount> DealerDefinedServicesDiscounts { get; set; }
    ...
}

And I have a controller that can receive that model:

[HttpPost]
public ActionResult Edit(Dealer model)
{
    if (ModelState.IsValid)
    {
        dealerService.EditDealer(model);

        return RedirectToAction("Index");
    }
    return View("Create", model);
}

In my Angular.js controller I am trying to send this object:

{
  "DealerDefinedServices": [
    {
      ...
    }
  ],
  "DealerDefinedServicesDiscounts": [
    {
      ...
    }
  ]
}

If both "DealerDefinedServices" and "DealerDefinedServicesDiscounts" parameters are set, ASP.NET controller receives only one of them, but other becomes null. I was trying to fix this problem for hours and finally fixed it by renaming one of mentioned parameters because I thought that maybe the problem is that parameters have similar names. So, what's the problem, why controller can't see one of parameters if they have simillar names?

11
  • 1
    It might be the FormValueProvider in the model binder getting confused. It has a ContainsPrefix(String) method which might be the culprit. Can you try renaming the second parameter to Dealer1DefinedServices Discounts and try again and see if it works ? Then try it again by naming it DealerDefinedServices1Discounts and check again . If its the ContainsPrefix the former should work for u and the later should reproduce the null issue. Commented Nov 25, 2015 at 14:50
  • 1
    The default model binder uses a FormValueProvider to extract a fields value out of the request and put it into the Dealer model. ContainsPrefix is one of the methods it uses to find the field in the request in this case your $scope.model object. My guess is the ContainsPrefix is returning incorrect info to the model binder since the prefix "DealerDefinedServices" is common for both the properties in your model. I do not have enough knowledge about model binders to comment on what is the sequence of execution of code and why model binder makes one property null Commented Nov 25, 2015 at 15:09
  • 1
    But the fact that if you make sure that the prefix strings different on the 2 properties makes the binding work would point to ContainsPrefix being the culprit. Check this articke if you want a general idea of model binders chimera.labs.oreilly.com/books/1234000001708/… it is geared more towards a custom model binder implementation than explaining the default one but it should give you a idea of what FormValueProvider are. Commented Nov 25, 2015 at 15:16
  • 1
    Another thing to try might be to use a WebAPI instead of a action method in MVC , The model binders for Action methods expect to receive a form object ( hence the name FormValeProvider) . Since what you are passing is essentially a json a WebAPI model binder might be more efficient in binding it Commented Nov 25, 2015 at 15:16
  • 1
    Let me know if this is helpful and i will put it together in a answer. Commented Nov 25, 2015 at 15:17

2 Answers 2

1

It might be the FormValueProvider in the default model binder getting confused. It has a ContainsPrefix(String) method which might be the culprit. Try renaming the second parameter to

Dealer1DefinedServicesDiscounts

and then try it again by naming it

DealerDefinedServices1Discounts

The former should work properly while in the later should reproduce the null issue.

Reason for this behaviour

The default model binder uses a FormValueProvider to extract a fields value out of the request and put it into your Dealer model. FormValueProvider uses the ContainsPrefix methods to find the field in the request in this case your $scope.model object. My guess is the ContainsPrefix is returning incorrect info to the model binder since the prefix DealerDefinedServices is common for both the properties in your model.

I do not have enough knowledge about model binders to comment on what is the sequence of execution of code and why model binder makes one property null.

As you have already tried already changing the property names so that they dont have same prefixes will work around this problem.

Another thing to try might be to use a WebAPI instead of a action method in MVC. The model binders for Action methods expect to receive a form object ( hence the name FormValueProvider) . Since what you are passing is essentially a json/javascript object a WebAPI model binder might be more efficient in binding it. Note : I havent tried it , it WebAPI may have the same issue.

Sign up to request clarification or add additional context in comments.

Comments

0

It is a bug in MVC4. Be careful. http://aspnetwebstack.codeplex.com/workitem/616

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.