passing list of objects in controller using ajax call - c#

I am trying to passing List to controller method using ajax. example I am 2 objects in the list like below. I am getting two objects in controller but inside properties are null
var dataObject = { 'sections': sectionsOrder};
console.log(dataObject);
CustomAjaxRequest("Post", "#Url.Action("UpdateOrderHoldingsForSections", "Renewal")" ,
dataObject, "json", "UpdateSectionsViewWithLatestOrderHoldings",
null, true);
[HttpPost]
public ActionResult UpdateOrderHoldingsForSections(List<OrderHoldings> sections)
{
return null;
}
even I tried var dataObject = { 'sections': json.stringify(sectionsOrder)}; still nothing working. What could be the problem?
In Console before passing values

Your controller is expecting a List, but you're passing up an object with a property that is a list. Try sending up the array directly, it should map to List
CustomAjaxRequest("Post", "#Url.Action("UpdateOrderHoldingsForSections", "Renewal")" ,
sectionsOrder, "json", "UpdateSectionsViewWithLatestOrderHoldings",
null, true);
Or you could instead add a C# binding model which has a property public List<OrderHoldings> Sections { get; set; }

Here is how I would do:
var jsonData = JSON.stringify(sectionsOrder);
var dataObject = { sections: jsonData };
CustomAjaxRequest("Post", "#Url.Action("UpdateOrderHoldingsForSections", "Renewal")" , dataObject, "json", "UpdateSectionsViewWithLatestOrderHoldings", null, true);
And then in controller,
[HttpPost]
public ActionResult UpdateOrderHoldingsForSections(string sections)
{
List<OrderHoldings> sectionsHoldings;
JavaScriptSerializer seriliazer = new JavaScriptSerializer();
sectionsHoldings = seriliazer.Deserialize<List<OrderHoldings>>(sections);
.
.
.
}
and yes, make sure that you are accepting string in the controller as seen above and not List

Related

Call Method in Controller from View(cshtml)

Hi im trying to call a method from controller from view just to display the "staff_name"
Controller
public JsonResult getStaffName(int staff_id)
{
var staffname = (from a in db.master_staff where b.staff_id == staff_id
select a.staff_name).SingleOrDefault();
return Json(staffname,JsonRequestBehavior.AllowGet);
}
View
int[] staff_id = { 24,25,26 };
#foreach (var n in staff_id){
//call method getStaffName from Controller to get "staff_name"
}
it suppose to get the "staff_name" according to the "staff_id"
is there any possible method for this situation?
To call method from controller to view you have to use ajax call from view.
here is ajax call syntax in asp.net mvc:
$.ajax({
type: "GET",
url: '#Url.Action("controller method name", "controller name")',
data: { searchText: value },
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function (result) {
},
error: {
}
});
type can be GET or POST depending on your controller method type.
In URL attribute two parameters are passed the first one is controller method name and second one is controller name.
In data attribute you have to pass the values which are required to pass in controller from view such as parameters in controller method.
In success and error attribute you have to write a block of code which should be executed in both cases. such as display data on UI upon success and error message on failure.
Do not do this. It is the way to the Dark side :) And each JSON request is taking some time.
Create model to store your staff
Fill it in controller (or even better in some business logic class)
Display in your view
public ActionResult Staff()
{
// This would be nice to have as separate Data Access Layery class
var staffs = GetStaffs();
return View(staffs);
}
private static StaffDto[] GetStaffs()
{
// One call to database is better that several
var staffs = db.master_staff
.Where(x => x.staff_id > 0) // Any other condition, if needed
.Select(x => new StaffDto(x.staff_id, x.staff_name))
.ToArray();
return staffs;
}
// Data Transfer Object class to separate database from presentation view
public class StaffDto
{
public int StaffId { get; set; }
public string Name { get; set; }
public StaffDto(int staffId, string name)
{
StaffId = staffId;
Name = name;
}
}
Your view file (Staff.cshtml in my case)
#model IEnumerable<TestMvc.Controllers.StaffDto>
<div>
#foreach (var staff in Model)
{
#staff.Name<br />
}
</div>
And, as bonus, you could unit test it easily
private readonly HomeController _homeController = new HomeController();
[TestMethod]
public void Staff_CheckCount()
{
var result = _homeController.Staff();
Assert.IsInstanceOfType(result, typeof(ViewResult));
var actual = ((ViewResult)result).Model as StaffDto[];
Assert.IsNotNull(actual);
Assert.AreEqual(3, actual.Length);
}
You can do it like this:
#Html.Action("getStaffName", "YourController", staff_id)
For more info, look at child actions: https://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx/
However, I do not know what you are trying to achieve with this.

How to pass data like an anonymous object from Jquery datatable in asp.net mvc

I have a Jquery datatable in my ASP.NET MVC view. The columns are like this :
"columns": [
{ "data": "Vote", "autoWidth": true },
{ "data": "Answer1", "autoWidth": true },
{ "data": "View", "autoWidth": true },
{
"data": "Title", "autoWidth": true,
'render': function (Title)
{
//return '<a href=' + Title + '>' + Title + '</a>';
return '<a href=/Questions/GoForAnswer/?idForAnswer='+ 2+'&title=dfg&question=dfg&view=59&date=08%2F10%2F2016%2023%3A39%3A17&answerNumber=13&vote=113>' + Title + '</a>';
}
}
]
Here in title column, I have hard coded the url that returns bunch of objects.But these objects are dynamic. I want to send these into the query string. Like I used to send them like this :
#Html.ActionLink(item.Title, "GoForAnswer", new { idForAnswer = item.ID, title = item.Title, question = item.Question, view = item.View, date = item.Date, answerNumber = item.Answer1, vote = item.Vote })
How can I send the objects from my Jquery function.
What you can do is you can make a model with the same names as your object example:
public class PeopleObject
{
public string name {get;set;}
public int age {get;set;}
}
then all you have to do is make you jquery object with the same names example:
var uniqueObjectName = [{name:'example1',age:20},{name:'example2',age:30}];
then after that you send the jquery object to you controller with ajax and pass the object as a variable example of ajax:
var uniqueObjectName = [{name:'example1',age:20},{name:'example2',age:30}]; // #1
$.ajax({
type: 'POST',
data: uniqueObjectName , // #2
url: '/Home/SubmitMyData',
//contentType: 'application/json', #3
//dataType: 'json', #2
success: alert('Youhou'),
error: alert('not good')
});
in you controller you receive the object like :
public ActionResult Index(PeopleObject uniqueObjectName )
{
return View();
}
notice the controller parameter name and the jquery variable name is the same...
The controller will automatically map the object to the model
Better construct your query in a different way, instead of passing the url directly to $.ajax, modify it to meet your needs.
So, essentially you store the razor generated URL, from #Html.RouteUrl method, in a JavaScript variable. Then you append the query string.
Because, in this case, the query string contains dynamic values, meaning some might not be listed in every request you need to have them listed in a placeholder variable, and replace values accordingly.
After you done with that, you just append the query string to the base URL and provide it to $.ajax.
Take a look at the following example (I have included a fiddle link to see it in action). I store the #Route.Url generated URL in the url variable. I also have declared all the keys of the model in keys table, as well as defined a placeholder string to replace values accordingly.
In fixPlaceholder method I just replace all the {key}=${placeholder} occurrences with the value of my data object (from there you get your dynamic values) or empty (if the value is not set for that particular property).
Finally, I append the placeholder to the url and pass it to $.ajax. Binding will do its magic on the ASP.NET MVC side, so do not worry about that, just declare your controller's action normally, expecting a complex object, like in this example:
[HttpGet]
public JsonResult GetModelAction(SampleViewModel model) {
// Your code here...
}
For your client code you can have something like this:
function fixPlaceholder (keys, data, placeholder) {
for(var i = 0; i < keys.length; i++) {
placeholder = placeholder.replace(keys[i] + "=${PLACEHOLDER}", keys[i] + "=" + (data[keys[i]] || ""));
}
return placeholder;
}
$(function(){
$("button").on("click", function () {
var keys = ["Title", "Question", "AnswerNumber", "View", "Date", "Vote"];
var data = {Title:"Myitle", Question:"MyQuestion", Vote:"10"};
var placeholder = "?Title=${PLACEHOLDER}&Question=${PLACEHOLDER}&AnswerNumber=${PLACEHOLDER}&View=${PLACEHOLDER}&Date=${PLACEHOLDER}&Vote=${PLACEHOLDER}";
var url = '#Url.RouteUrl(new{ action="GetModelAsJson", controller="Home"})';
placeholder = fixPlaceholder(keys, data, placeholder);
url = url + placeholder;
$.ajax({
url: url,
type: "GET",
contentType: "application/json; charset=utf-8"
}).then(function(resp) {
console.log("Response");
console.log(resp);
});
});
Here is a dotnetfiddle, check it and try to work your way based on that. Hope this helps.
Note
Because you are using values that might not be set in the model in every request, meaning they might be null, you need to pay attention to your back-end model. That said, if you have any properties with types like int, DateTime, etc. you might need to mark them as nullable, in order to avoid hairy situations. Like the model below.
using System;
namespace HelloWorldMvcApp
{
public class SampleViewModel
{
public string Title { get; set; }
public string Question { get; set; }
public int? AnswerNumber { get; set; }
public string View { get; set; }
public DateTime? Date { get; set; }
public string Vote { get; set; }
}
}

ASP.NET MVC JSON body with POST

I am new to ASP.NET MVC and learning. So far I have figured out how I can create a JSON Object and return that as a response to a request. However, I'm not able to pass a JSON body as part of a POST request like I normally did using Java.
Here is the code how I did this there -
#Path("/storeMovement")
#POST
#Consumes("application/json")
#Produces("application/json")
public String storeTrace(String json) {
JSONObject response = new JSONObject();
JSONParser parser = new JSONParser();
String ret = "";
try {
Object obj = parser.parse(json);
JSONObject jsonObj = (JSONObject) obj;
RecordMovement re = new RecordMovement((double) jsonObj.get("longitude"), (double) jsonObj.get("latitude"), (long) jsonObj.get("IMSI"));
ret = re.Store();
// Clear object
re = null;
System.gc();
response.put("status", ret);
} catch (Exception e) {
response.put("status", "fail " + e.toString());
}
return response.toJSONString();
}
I tried the same in the ASP.NET Action method but the value in the string parameter a is null as seen while debugging. Here's the code for the Action method -
public string Search(string a)
{
JObject x = new JObject();
x.Add("Name", a);
return x.ToString();
}
It works fine when I use an Object (for example - Book) like so -
public string Search(Book a)
{
JObject x = new JObject();
x.Add("Name", a.Name);
return x.ToString();
}
In that case, the book's name gets de-serialized just fine as I would expect. The class definition for the Book class -
public class Book
{
public int ID { get; set; }
public string Name { get; set; }
}
Can somebody please advise what I'm doing wrong? Is there no way to take in a string and then de-serialize? I'd like to be able to take in JSON without having to use an Object
As for as understand you want pass entire of request body to a string without any binding so you could handle passed string data with your desired way.
To aim this purpose simply write your own model binder:
public class RawBodyBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if(typeof(string)!=bindingContext.ModelType)
return null;
using (var s = new StreamReader(controllerContext.HttpContext.Request.InputStream))
{
s.BaseStream.Position = 0;
return s.ReadToEnd();
}
}
}
And in you action method assign your binder to desired parameter:
public string MyAction([ModelBinder(typeof(RawBodyBinder))]string json)
{
}
But MVC has own JSON model binder as well if your data is a standard JSON and in request body with Content-Type: application/json header you could use MVC's JSON model binder to activate JSON model binder simply add following line in Global.asax.cs file:
protected void Application_Start()
{
// some code here
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}
The first thing in asp.net mvc to post a data is to decorate the method with this attribute [Httpost]
it's mean passing a string
should look like
[HttpPost]
public string Search(string a){
// your code
}
The default value is [HttpGet] that get parameters from url. For Post request you need to.
Edit:
And look the answer from vinayan
with jquery:
$.ajax({
method: "POST",
url: "Home/Search",
data: {'a': 'yourstring'}
})
The name of the parameter you send is used for the de-serialization. So in in this case, "a" should be part of json.
public string Search(string a)
so you will have to use,
$.ajax({
method: "POST",
url: "Home/Search",
data: {'a': 'yourstring'}
})

json data not received by asp.net mvc action method

I am trying to get some data to a controller from client side script, I am stringfying my data so I receive something like:
{"Name":"","Description":"","FieldType":"radio","Fields":[{"Field":{"Name":"something","Value":"nameit"}},{"Field":{"Name":"something else","Value":"dontnameit"}}]}
I will need to validate my data on the controller however, in my action I am recieving a null for some reason, if I use object or string? Why is that?
I have had a look into a lot of other posts but it is not clear, do I need to create my own custom IValueProvider implementation? I think there is one available in the ms futures assembley, I tried to locate the file as I do not want all the code inside the dll, but I could not find it...
Any pointers would be appreciated...
Controller:
[HttpPost]
public JsonResult AddField(string field) //or object
{
//code here
}
Edit: I have followed the post by phill haack but had some errors actually returning the strongly typed object to my view...
my ajax call..
{
url: url,
type: "post",
dataType: 'json',
traditional: true,
data: jsondata, // { "field" : jsondata},
contentType: 'application/json; charset=utf-8',
...
}
I created a custom value provider...
public class Jsonify : ValueProviderFactory
{
public Jsonify() { }
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
var jsonData = GetDeserializedJson(controllerContext);
if (jsonData == null)
{
return null;
}
//currently used by mvc2 futures
//return new DictionaryValueProvider<object>(backingStore,
//CultureInfo.CurrentCulture);
// what do I return?
}
private static object GetDeserializedJson(ControllerContext controllerContext)
{
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
// not JSON request
return null;
}
StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
string bodyText = reader.ReadToEnd();
if (String.IsNullOrEmpty(bodyText))
{
// no JSON data
return null;
}
//json.net
var jsonData = JsonConvert.DeserializeObject<SurveyField>(bodyText);
return jsonData;
}
}
Controller:
public JsonResult AddSimpleField(SurveyField field) { ... }
You may take a look at the following blog post which illustrates how you could use a custom JsonValueProviderFactory to send a JSON encoded string from client scripts to a controller action and have this action receive it as a strongly typed model and benefit from the validation of the default model binder:
[HttpPost]
public ActionResult AddField(SomeViewModel model)
{
if (!ModelState.IsValid)
{
// the client sent an invalid data
return Json(new { IsSuccess = false });
}
// the model passed validation => do some processing with this model
return Json(new { IsSuccess = true });
}
As Phil Haack explains it this custom JsonValueProviderFactory is only necessary if you are working with ASP.NET MVC 2 and is built-in ASP.NET MVC 3 so it should work out of the box.

Can i convert JSONResult to IEnumerable list in C#

I have a function that send a JSONResult, Now i want to use that function in C# and convert that JSONResult to IEnumerable so i can iterate on that result and pass that data to a SelectList function. Can i do this and how? Im using Asp.Net MVC, JQuery and C#
why not:
public myObject GetMyObject()
{
myRepository db = new myRepository();
return db.ListAllStuff();
}
public JsonResult GetMyJSON()
{
return Json(GetMyObject(), JsonRequestBehavior.AllowGet);
}
public List<SelectList> GetMyEnumerable()
{
return this.GetMyObject().ToList();
}
and you are reusing everything.
Also it can be done in this way.
var data = GetJsonResultData(); //call to JsonResult method.
var datastr = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(data.Data); // convert json object to string.
var dataclass = Newtonsoft.Json.JsonConvert.DeserializeObject<List<modeldto>>(datastr ); // string json data to class list

Categories