cindy
cindy

Reputation: 11

How to send complex types to MVC2 controller via Jquery (Ajax )

I am posting a Jquery Json serialized object to my controller but not all of the data is getting passed. One of the members is a complex type that is also Json serialized. This is the one that isn't getting through to the controller.

Here is the class I'm passing to my controller via Ajax post. Note the complex type, RoutingRuleModel.

SourceCodeModel.cs:

[Serializable]
public class SourceCodeModel
{
    public string SourceCode { get; set; }
    public bool IsActive { get; set; }
    public string LastChangedBy { get; set; }
    public string LocationCode { get; set; }
    public string Vendor { get; set; }
    public RoutingRuleModel RuleModel { get; set; }
}

RoutingRuleModel.cs:

[Serializable]
public class RoutingRuleModel
{
    public string AdaStuInfoSysId { get; set; }
    public string AdaInitials{ get; set; }
    public string LocationCode { get; set; }
    public string Vendor { get; set; }
    public string RuleName { get; set; }
    public string RuleStatus { get; set; }
    public int RuleId { get; set; }
}

Here is how I am building the model in JavaScript:

getSourceCodeModel = function (sourceCode, isActive, lastChangedBy, locationCode,   ruleModel) {
    // Retrieves a SourceCodeModel object that can be JSON-serialized
    return ({
                    SourceCode: sourceCode,
        IsActive: isActive,
        LastChangedBy: lastChangedBy,
        LocationCode: locationCode,
        Vendor: ruleModel.Vendor,

        RuleModel: [{ AdaStuInfoSysId: ruleModel.AdaStuInfoSysId, AdaInitials: ruleModel.AdaInitials, LocationCode: ruleModel.locationCode, 
            Vendor: ruleModel.Vendor, RuleName: ruleModel.RuleName, RuleStatus: ruleModel.RuleStatus, RuleId: ruleModel.RuleId}]
    });
};

Here is my JQuery Ajax call:

$.ajax({
            type: "POST",
            url: "/LeadRoutingConsole/VendorLeadRouting/PostSourceCode",
            data: sourceCodeModel,
            datatype: "json",
            success: Commit_success,
            error: Commit_error,
            complete: function (jqXHR) { }
        });

Here is my controller's action method:

[HttpPost]
    public JsonResult PostSourceCode(SourceCodeModel model)
    {
        // perform the save op
        var viewModel = new SourceCodesViewModel();
    viewModel.PostSourceCode(model);
        return Json(model);
    }

Problem: SourceCodeModel contains correct values EXCEPT for it's complex member: RuleModel, which comes back as a RoutingRuleModel with default (null or 0's) values.

Upvotes: 1

Views: 1172

Answers (2)

kaps
kaps

Reputation: 478

You can write a CustomFilterAttribute on controller action and deserialize the json object in your CustomFilterAttribute class. Something like...

public class JsonFilter : ActionFilterAttribute
{
    public string Param { get; set; }        
    public Type JsonType { get; set; }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SourceCodeModel));
       filterContext.HttpContext.Request.InputStream.Position = 0;
       SourceCodeModel result = serializer.ReadObject(filterContext.HttpContext.Request.InputStream)
              as SourceCodeModel;
       filterContext.ActionParameters[Param] = result;
    }
}

and controller action...

[HttpPost]
[JsonFilter(Param = "sourceCodeModel", JsonType = typeof(SourceCodeMode))]
public JsonResult PostSourceCode(SourceCodeModel model)
{...}

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038810

You are trying to send a collection as RuleModel whereas that's not a collection property. So try like this (remove the square brackets [] around the RuleModel property definition):

getSourceCodeModel = function (sourceCode, isActive, lastChangedBy, locationCode,   ruleModel) {
    return ({
        SourceCode: sourceCode,
        IsActive: isActive,
        LastChangedBy: lastChangedBy,
        LocationCode: locationCode,
        Vendor: ruleModel.Vendor,
        RuleModel: { 
            AdaStuInfoSysId: ruleModel.AdaStuInfoSysId, 
            AdaInitials: ruleModel.AdaInitials, 
            LocationCode: ruleModel.locationCode, 
            Vendor: ruleModel.Vendor, 
            RuleName: ruleModel.RuleName, 
            RuleStatus: ruleModel.RuleStatus, 
            RuleId: ruleModel.RuleId
        }
    });
};

Also never hardcode urls as you did in your javascript. Always use Url helpers when dealing with urls or you might get bad surprises when you deploy your application:

$.ajax({
    type: 'POST',
    url: '<%= Url.Action("PostSourceCode", "VendorLeadRouting") %>',
    data: sourceCodeModel,
    dataType: 'json',
    success: Commit_success,
    error: Commit_error,
    complete: function (jqXHR) { }
});

Also notice that the parameter is called dataType: 'json' instead of datatype: 'json' which is important with a case sensitive language such as javascript.

Upvotes: 1

Related Questions