Pass JSON to MVC 3 Action
I am trying to submit JSON to a MVC action. What I want is to take the JSON object and then 开发者_Go百科access it's data. The number of JSON fields will vary each time so I need a solution that will handle all cases.
This is my POST to my action, address could have 3 fields or 20 it will vary on each post.
Update: I'll go into a little more detail. I'm trying to use the LinkedIn API, I'll be sent a JSON which will look like the JSON at the end of this page : link. I need to create an Action which will accept this JSON which will vary for every person.
var address =
{
Address: "123 rd",
City: "Far Away",
State: "Over There"
};
$.ajaxSetup({ cache: false });
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Account/GetDetails/",
data: JSON.stringify(address),
dataType: "json",
success: function () {
alert("Success from JS");
}
});
This is my action in MVC, I need to be apply to take whatever JSON object is passed and access its fields.
[HttpPost]
public ActionResult GetDetails(object address)
{
//address object comes in as null
@ViewBag.Successs = true;
return View();
}
I don't believe nobody saying this so I will try. Have your code like this
public class Personal
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
//other properties here
}
[HttpPost]
public ActionResult GetDetails(Personal address)
{
//Should be able to get it.
@ViewBag.Successs = true;
return View();
}
In general, you can add those possible properties into the class Personal (or whatever you can name it). But according to linkedin API, you will need a tool to generate the data class due to its complexity. I think xsd.exe can help if you can get xsd file for that (or you can even generate xsd file from xml)
Remove
data: JSON.stringify(address)
withdata: address
Action method
[HttpPost] public ActionResult GetDetails(string Address, string City, string State, string PropName) { //access variable here }
As you have said your data object may contain 20 props, to avoid creating 20 parameters, you can use formscollection like below
[HttpPost]
public ActionResult GetDetails(FormCollection address)
{
string city= address["city"] ;
string anotherPro=address["prop"];
}
Not sure if this will work (never done this myself), but you could try the following signature:
public ActionResult LinkedIn(dynamic address)
I'm actually quite interested myself to see what will happen then. Or, as suggested in the comment by Kristof Claes, use a FormCollection
.
Second, when things like this happen, always check whether the browser actually sends the data you expected to the server. IE9 and Chrome support this out of the box, otherwise you can use a tool like Fiddler.
EDIT: Just tried for myself with a dynamic
parameter and that doesn't work.. The runtime type of the parameter is object
so everything you submitted is lost. You'd better
use FormCollection
.
I believe you can use a FormCollection
for this.
public ActionResult LinkedIn(FormCollection address)
{
var street = address["street"];
...
return View();
}
Might just be a typo, but you are calling GetDetails
ActionResult, but yet your code is LinkedIn
?
You need to wrap your JSON object in the name of parameter you are expecting in your action method. Something like this:
var data = { address: { address: '123 Test Way', city: 'Parts Unknown', state: 'TX' } };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Account/GetDetails/",
data: JSON.stringify(data),
dataType: "json",
success: function () {
alert("Success from JS");
}
Then in your action method, do this:
public ActionResult GetDetails(dynamic address) {}
My take is all the answers are sort of right.
As your don't know the number of things you're sending, use formcollection on the server. But also remove the stringfy from the ajax call. These means the data will be sent using www-encoding.
If you wnat to send n address objects, change the mvc action parameter to an array of address objects and use stringfy.
This is how I do it. I have a MyProject.Model.Entities and I serialize them in by using [ParamSerializationFilter] attribute on the given action method.
Full code here: https://gist.github.com/3b18a58922fdd8d5a963
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!Enum.GetNames(typeof(AllowedMethods)).Any(n => n == filterContext.HttpContext.Request.HttpMethod))
throw new InvalidOperationException("Invalid Request: HttpMethod");
foreach (var param in filterContext.ActionDescriptor.GetParameters())
{
if (ModelTypes.Contains(param.ParameterType))
{
if ((filterContext.HttpContext.Request.ContentType ?? string.Empty) == ("application/json"))
{
filterContext.ActionParameters[param.ParameterName] =
JsonSerializer.DeserializeFromStream(param.ParameterType, filterContext.HttpContext.Request.InputStream);
}
else if (filterContext.HttpContext.Request.ContentType.Contains("xml"))
{
filterContext.ActionParameters[param.ParameterName] =
XmlSerializer.DeserializeFromStream(param.ParameterType, filterContext.HttpContext.Request.InputStream);
}
}
}
}
You're doing too much work! You can pass the JSON Literal directly to the server and access the elements via the action method parameters, like this:
var address =
{
Address: "123 rd",
City: "Far Away",
State: "Over There"
};
$.ajaxSetup({ cache: false });
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Account/GetDetails/",
data: address,
dataType: "json",
success: function () {
alert("Success from JS");
}
});
[HttpPost]
public ActionResult LinkedIn(string Address, string City, string State)
{
// now you have everything you want as params
@ViewBag.Successs = true;
return View();
}
Note: This will only work if your action params are named the exact same as your JSON Literal attributes.
精彩评论