0

I have a view that I'm binding with knockoutjs. I need to add data dynamically to a list in the viewmodel using ajax post.

            var data = {
                model: ko.toJS(self.Model),
                name: name
            }

             $.ajax({
                url: options.url + "AddAdvantage",
                type: 'POST',
                dataType: 'json',
                contentType: 'application/json',
                data: JSON.stringify(data),
                traditional: true,
                success: function (data) {
                    self.UpdateOnChange = false;
                    ko.mapping.fromJS(data, self.Model);
                    self.UpdateOnChange = true;
                }
            });

when the data parameter is passed to the controller action:

[HttpPost]
public JsonResult AddAdvantage([ModelBinder(typeof(AdvantageModelBinder))] AdvantageViewModel model, string name) {
}

name value is passed, but model is always null

I have tried this:

            var data = {
                model: ko.toJSON(self.Model),
                name: name
            }

also tried:

            var data = JSON.stringify({
                model: ko.toJSON(self.Model),
                name: name
            });

same result.

this works fine:

           $.ajax({
                url: options.url + "AddAdvantage",
                type: 'POST',
                dataType: 'json',
                contentType: 'application/json',
                data: ko.toJSON(self.Model),
                traditional: true,
                success: function (data) {
                    self.UpdateOnChange = false;
                    ko.mapping.fromJS(data, self.Model);
                    self.UpdateOnChange = true;
                }
            });

My ModelBinder

public class AdvantageModelBinder: DefaultModelBinder
{
    public AdvantageModelBinder()
    {
    }

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue("WizardType");
        Type typeByTypeName = AdvantageModelBinder.GetTypeByTypeName((string)value.ConvertTo(typeof(string)));
        object obj = Activator.CreateInstance(typeByTypeName);
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => obj, typeByTypeName);
        return obj;
    }

    public static Type GetTypeByTypeName(string typeName)
    {
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        for (int i = 0; i < (int)assemblies.Length; i++)
        {
            Type type = assemblies[i].GetType(typeName, false, true);
            if (type != null)
            {
                return type;
            }
        }
        throw new ArgumentException("Can't find the specified type in the loaded assemblies.", typeName);
    }
}

can anyone tell how to fix this?

6
  • Is the value of ko.toJS(self.Model) is an js object? Commented Apr 21, 2016 at 10:40
  • Did you try to debug the AdvantageModelBinder? Also why are you calling WizardModelBinder inside AdvantageModelBinder Commented Apr 21, 2016 at 10:44
  • I'm not calling WizardModelBinder, it was a pasting error. Commented Apr 21, 2016 at 11:18
  • If ko.toJS(self.Model) is js object, then try this - var data = ko.toJS(self.Model); use this url - options.url + "AddAdvantage?name="name Commented Apr 21, 2016 at 11:35
  • Yes, Karthik that works, But I didn't want to pass it as a query string because in some instance, I might be passing up to six parameters. Commented Apr 21, 2016 at 11:53

2 Answers 2

1

Seems that you're not passing exactly the same object in the payload.

Let's say that your model object is like this:

{
   foo: 1,
   bar: 2
}

On the first two samples you are creating this object:

{
   model: {
             foo: 1,
             bar: 2
          },
   name: "whatever"
}

So, when you pass it as an argument to the ajax call you're passing an object that is not expected on the MVC side.

If you want to store it in a variable, you need to do the following:

 var data = ko.toJSON(self.model)

And make the ajax call doing this:

 $.ajax({
            url: options.url + "AddAdvantage",
            type: 'POST',
            dataType: 'json',
            contentType: 'application/json',
            data: data,
            traditional: true,
            success: function (data) {
                self.UpdateOnChange = false;
                ko.mapping.fromJS(data, self.Model);
                self.UpdateOnChange = true;
            }
        });
Sign up to request clarification or add additional context in comments.

Comments

0

Try this:

var data = {
  model: self.Model,
  name: name
}

$.ajax({
  url: options.url + "AddAdvantage",
  type: 'POST',
  dataType: 'json',
  contentType: 'application/json',
  data: ko.toJSON(data),
  traditional: true,
  success: function (data) { ... }
});

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.