4

I'm using ASP.NET MVC and jQuery to save some data via AJAX calls. I currently pass in some JSON data using the jQuery ajax() function like so

$.ajax({
    dataType: 'json',
    type: 'POST',
    url: '@Url.Action("UpdateName", "Edit")',
    data: {
        id: 16,
        name: 'Johnny C. Bad'
    }
});

using this controller method and helper class.

public void UpdateName(Poco poco)
{
    var person = PersonController.GetPerson(poco.Id);   
    person.Name = poco.Name;
    PersonController.UpdatePerson(person);
}

public class Poco
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Another way of accepting the JSON data is to simply use multiple arguments like this

public void UpdateName(int id, string name)
{
    var person = PersonController.GetPerson(id);    
    person.Name = name;
    PersonController.UpdatePerson(person);
}

This approach is ok for a smaller number of arguments, but my real world code has usually has about 5 - 10 arguments. Using an object instead of having to declare and use all these arguments is very handy.

I'm wondernig if there is another way of accepting the JSON data as a single object and not having to declare a class for each controller method I want to use this approach in. For example, something like this:

public void UpdateName(dynamic someData)
{
    var person = PersonController.GetPerson(someData.Id);   
    person.Name = someData.Name;
    PersonController.UpdatePerson(person);
}
4
  • you can certainly post complex objects as long as you convert them to JSon. Will you be building your complex object in jscript or from Razor variables? Commented Feb 13, 2013 at 16:10
  • Another option would be to take in the json data as a string and deserialize in the action. Commented Feb 13, 2013 at 16:11
  • stackoverflow.com/questions/11608026/… Commented Feb 13, 2013 at 16:12
  • The object comes from a JavaScript object. Commented Feb 13, 2013 at 16:44

4 Answers 4

3

You can accept a FormCollection, it will look like:

public void UpdateName(FormCollection collection)
{
    var person = PersonController.GetPerson(int.Parse(collection["id"]));
    person.Name = collection["name"];
    person.Age = collection["age"];

    PersonController.UpdatePerson(person);
}
Sign up to request clarification or add additional context in comments.

Comments

1

Possible solution

Create specific model binder, for example as



    public class DynamicModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (controllerContext.HttpContext.Request.Form.AllKeys.Any(x => x == "dynamic"))
            {
                dynamic model = new ExpandoObject();
                IDictionary underlyingmodel = model;

                foreach (var key in controllerContext.HttpContext.Request.Form.AllKeys)
                    underlyingmodel.Add(key, (bindingContext.ValueProvider.GetValue(key).RawValue as string[]).First());

                return model;
            }

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

This binder will check for specific input with name "dynamic" then create dynamic object



    public ActionResult Index()
    {
       return View();
    }

    [HttpPost]
    public ActionResult Index(dynamic input)
    {
       ViewBag.Result = input.phrase;
       return View();
    }

Comments

1

I am not quite sure why you want to achieve that, but you can achieve it using dynamic (I didn't try this):

public void UpdateName(string parameters)
{
    var dynamicObject = Json.Decode(parameters);
}

Json.Decode is in System.Web.Healpers namespace

And you can passed them at javascript as follows:

var dataObject = JSON.stringify({ id: '1', name: 'John' });
$.ajax({
    dataType: 'json',
    type: 'POST',
    url: '@Url.Action("UpdateName", "Edit")',
    data: dataObject 
});

Comments

0

I suppose the issue here is knowing exactly what common functionality you want to be shared in your controller between entities. If all this functionality can be unified behind some shared property (from the above example, maybe the Id and Name fields?) Then you could pass instances of IEntity back and forth, or some base class which contain those 2 properties.

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.