ASP.NET MVC Can JSON object be passed to a controller with parameter with dynamic type parameter? - ajax

I have code in my javascript, a ajax to post data:
$.ajax({
url: '/Configurations/GetSelectedPageTranslation',
type: 'POST',
data: { inttype: $("#some").val(), objectType:{prop1: 'adsfa', prop2: 'asdf'}},
success: function (result) {
},
error: function () {
alert('error');
}
});
In the contoller i have a method with signature:
public JsonResult GetSelectedPageTranslation(int inttype, dynamic objectType)
I can have the inttype correctly. However the objectType will not be null but if i do like objectType.prop1, it will throw error. If i will JSON.stringify the object type in the javascript, the objectType in the controller will have a string value.
Could this be possible to directly access the JSON data in the controller using the dynamic data type like this: objectType.prop1 ?
Thanks

There is no out of the box support for dynamic action arguments in MVC3.
However MVC is very extensible so you can add this functionality. What you need to do is to create a custom IModelBinder where you can do the JSON deserialization and build up a dynamic object.
Luckily this article: Making MVC 3 a little moreā€¦ dynamic is dealing with the exact same problem, so you can find also sample code and additional links there which should help you get started.

Related

How to post part of the viewmodel to a Web API controller

I have a VB Web API app.
I have a VB class/model like so.
Imports System.ComponentModel.DataAnnotations
Imports System.Web.Http
Public Class MSLDestinationInput
<HttpBindRequired>
<Required>
Public Property ShpmntCntrlNbr() As String
Get
Return m_ShpmntCntrlNbr
End Get
Set(value As String)
m_ShpmntCntrlNbr = value
End Set
End Property
Private m_ShpmntCntrlNbr As String
End Class
This is the controller:
Public Async Function GeneratePDF(data As MSLDestinationInput) As Task(Of IHttpActionResult)
If Not ModelState.IsValid Then
Return BadRequest(ModelState)
End If
Dim oMSLOutput As New MSLOutput
oMSLOutput.url = "api/PrintGenerateMSL"
Return Ok(oMSLOutput)
End Function
I am posting to the controller using jQuery.ajax with this parameters:
url: 'api/PrintGenerateMSL',
data: ko.toJSON(self),
type: "POST",
and everything is working well. However I don't really need to send the entire knockout model. I just need to send some of the properties. I've tried to send this data:
data: {ShpmntCntrlNbr : self.ShpmntCntrlNbr() };
instead of ko.toJSON(self). When the request reaches my controller, I find the parmeter data is empty.
How can I send only the required data to my controller instead of the whole ko view model?
You need to stringify the data. One way to do it is by using JSON.stringify, as you've done.
Most, but not all browsers, include the JSON manipulation functions. The problem is that if someones tries to use your application in a browser that doesn't have this methods, it will crash. Or you'll have to suplly a polyfill.
The good news is that you don't need to worry about it if you use ko.toJSON. In fact ko.toJSON does two things:
unwraps all the observables, if they exist
convert to JSON, by using JSON.stringify
That means that both of this options would work fine:
data: ko.ToJSON({ShpmntCntrlNbr : self.ShpmntCntrlNbr() })
data: ko.ToJSON({ShpmntCntrlNbr : self.ShpmntCntrlNbr })
Note that the property on the second one would be automatically unwrapped. If you took a piece of your viewmodel which is an object tree that includes some observable properties at any level, ko would also unwrap them automatically.
And, best of all, if the browser does not implement JSON.stringify, ko provieds its own implementation.
yes stringify took care of it. it is working now with.
data: JSON.stringify({ShpmntCntrlNbr : self.ShpmntCntrlNbr() }),

How do I cause an MVC controller to redirect the user from an ajax call?

I am sending an array as the "data" value (parameters) of an ajax call to an MVC controller. The controller should then redirect the user to a new page but it does not. Instead I can see in the Preview window that the View is being returned but through the ajax return. I am not sure if the way I am approaching this is correct because I seem to be having a hard time finding good examples to follow. I wanted to avoid an Html.ActionLink because I will have about 20 parameters to pass to the controller.
Here is the function that sends the array to the controller:
submit: function () {
var data = {
"ReqDepartment": (viewModel.reqDepartment === null) ? null : viewModel.reqDepartment,
"EquipmentGroup": (viewModel.equipmentGroup === null) ? null : viewModel.equipmentGroup,
"SiteCode": (viewModel.site === null) ? null : viewModel.site.SiteCode,
}; //header
$.ajax({
type: "POST",
url: "/ArctecLogisticsWebApp/Requisitions/ReqsSummary/",
data: data,
traditional: true
});
}
Here is the controller, ReqSearchCriteria is a ViewModel :
public ViewResult ReqsSummary(ReqSearchCriteria criteria)
{
return View("ReqsSummary", requisitionsRepository.GetReqsAdvancedSearch(criteria));
}
The controller is returning the View in the ajax call. Should I use a different approach to send an array to the controller?
ajax calls won't redirect by themselves. what you need to do is return json from the controller to the view with the result of the action and if the action is successful then redirect
$.ajax({
type: "POST",
url: "/ArctecLogisticsWebApp/Requisitions/ReqsSummary/",
data: data,
traditional: true,
success: function(result){
if(result.Success){
window.location = '#Url.Action('Action', 'Contorller')';
}
}
});
Edit:
The controller method you have will work. It should be a different name from the form you are redirecting from to eliminate confusion. Through data you can pass any information that you need.
data: { id: $('.id').val() },
something like this will pass whatever value is in the field with class id. then on your controller create the model for the view and return view. I use ajax calls everywhere, they are incredibly useful. Please let me know if you have any other questions.
You don't have to check for a result in your success/done handler and then do the redirect manually. You can actually return a JavascriptResult from your controller and it will redirect for you:
$.ajax({
type: 'post',
url: '/Home/DoStuff'
});
[HttpPost]
public ActionResult DoStuff()
{
return JavaScript(string.Format("window.location='{0}';", Url.Action("About")));
}
If you wanted to get fancy you could even create a new ActionResult type that took care of the formatting for you. Or you could detect if it is an AjaxRequest and determine if you should do a RedirectToAction or a JavaScript result.

MVC: How to serialize a knockout object into a JSON property through AJAX

I'm trying to serialize a knockout object and pass it into a JSON property called multipleCharge.
This is the ajax code to send data though Get method to a mvc controller
$.ajax({
url: _url,
type: 'GET',
//data: { multipleCharge: ko.mapping.toJS(_vm)},
data: { multipleCharge : { AccountId : 2 } },
dataType: 'json'});
And this is the method
[HttpGet]
public HttpResponseMessage GetSalesInvoiceMultipleCharge
([FromUri]MultipleChargeDto multipleCharge)
{
...
}
Please, note that the ajax method has a comment line. Using the hardcoded line, it works, multipleCharge object is not null, but if I uncomment the another line, it's a bad request in my browser.
Look at this.
Any idea about what's happening. Using the Chrome console, it looks ok; so I can't identify the error.
It is may be IIS problems with very long URL.
See this Issue with URL length in IIS7 (Windows Server 2008) question and related answers.
Also see this http://www.iis.net/configreference/system.webserver/security/requestfiltering documentation.
You could try to solve this problem by editing web.config. But also you could use POST method instead of GET and send your data in request body.

Deserializing into derived class in ASP.NET Web API

In my last SO question, I asked how to modify the serializer settings for Json.NET, which ASP.NET Web API natively uses for (de)serialization. The accepted answer worked perfectly, and I was, for example, able to embed type information into the serialized JSON string.
However, when I try to throw back this JSON string to a Web API action that's expecting the model's parent class, Web API still deserializes to the parent class, removes all data corresponding to the child class, and prevents casting to and detection of the child class.
class Entity { }
class Person : Entity { }
public Person Get() {
return new Person();
}
public bool Post(Entity entity) {
return entity is Person;
}
A simple use case would be doing something like this in jQuery:
// get a serialized JSON Person
$.ajax({
url : 'api/person' // PersonController
}).success(function (m) {
// then throw that Person right back via HTTP POST
$.ajax({
url : 'api/person',
type : 'POST',
data : m
}).success(function (m) {
console.log(m); // false
});
})
I'd expect that by modifying the JsonSerializerSettings of Json.NET to embed type information that it'd be able to read that and at the very least, try to force deserialization to that type, but apparently it does not.
How should I tackle something like this?
Web API really doesn't do any (de)serialization "natively". It happens to have a few MediaTypeFormatters included in the config.Formatters collection by default. Feel free to remove those and create your own MediaTypeFormatter that handles the serialization the way you want it to be done.
MediaTypeFormatters are really not that hard to create.
Actually the 2nd POST call is sending application/x-www-form-urlencoded data and that's why the type information is not picking up by the JsonMediaTypeFormatter. Try setting the contentType to be "application/json".
Also, the data in the 2nd POST request body seems to be encoded and it needs to be decoded before sending back to the service.
I was able to get this to work:
// get a serialized JSON Person
$.ajax({
url: 'api/person' // PersonController
}).success(function (m) {
// then throw that Person right back via HTTP POST
$.ajax({
url: 'api/person',
type: 'POST',
contentType: "application/json",
data: JSON.stringify(m),
}).success(function (m) {
alert(m); // true!
});
})

Controller action method call have the parameter as NULL while calling javascript in MVC3

I use MVC3.
I have `
function userLocation_change()
{
var text = $("#userLocation").val();
alert(text);
var url = '#Url.Action("GetAllLocations", "Home")';
var data = text;
$.post(url, data, function (result) {
});
}
`
Here is my controller action:
public JsonResult GetAllLocations(string userlocation)
{
///...some code...
return Json(..Something.., JsonRequestBehavior.AllowGet);
}
The problem is whenever the controller function is called "userlocation" parameter does have a NULL value. I want the data value would be passed to the controller action.
Could somebody plz tell me why this happens? Any update would be much appreciated.
Thanks.
You need to pass the parameter to the #Url.Action specifically via this overload method for Url.Action. You can use the RouteValueDictionary inline constructor with to instantiate.
Edit: realize now that you need that link to be populated at run time, but the Url.Action method generates the link at render time. I would suggest adding it to the query string and then reading it from the query string in your controller method. I suspect there is a more elegant way.. but I know this works.
something like: var url = '#Url.Action("GetAllLocations", "Home")?userlocation=' + $("#userLocation").val();
Modify your jQuery post function call as:
$.post(
url,
{ userlocation: text },
function(result){
....
});
This is because, you have to send data to the Controller's action method using JavaScript literal. You can view the full listing of different ways to call Controller's action using JavaScript here: http://www.asp.net/ajaxlibrary/jquery_posting_to.ashx
Your action has a string input parameter named userlocation, hence while sending the data to the action, you should specify this, like done in the code below.
Here I am using data: { userlocation: text},
function userLocation_change()
{
var text = $("#userLocation").val();
var url = '#Url.Action("GetAllLocations", "Home")';
$.ajax({
url: url,
type: 'POST',
data: { userlocation: text},
success: function (result) {
}
});
}
Hopes this solves your null problem.

Resources