Remove variable name from JSON data in ASP.NET MVC - c#

I'm trying to send a string of JSON to the client from a database for a JavaScript plugin to highlight the states it gets back. However, in addition to the state information I need, I'm also getting the variable name. Is there anyway I can correct the formatting so that instead of it looking like this:
{"statesHighilght":["California","Washington","Utah","Utah","Florida","Kansas","Utah"]}
I get this:
["California","Washington","Utah","Utah","Florida","Kansas","Utah"]
This is what my controller code looks like:
public ActionResult highlight()
{
var statesHighlight =
db.Jobs
.Select(r => r.State);
return Json(new { statesHighilght }, JsonRequestBehavior.AllowGet);
}

Pass the enumerable directly to the Json method instead of wrapping it in an anonymous object.
return Json(statesHighlight, JsonRequestBehavior.AllowGet);

Related

Getting empty array while ajax query to MVC controller

I am using $.ajax method to get the data from the MVC controller. I am usingPOST method according to the JSON Hijacking for security standards. If I debug I am able to get the data in controller, but after returning data to the $.ajax's success function then it is showing me empty json array like below.
In controller I am using method as below:
public async Task<ActionResult> GetUsersFromOrganization(string searchString) {
string accessToken = await SampleAuthProvider.Instance.GetUserAccessTokenAsync();
var result = await graphService.GetUsersFromOrg(accessToken, searchString);
var json = JObject.Parse(result);
var valueJSON = json.GetValue("value");
return Json(valueJSON, JsonRequestBehavior.AllowGet);
}
json contains below data:
Here is the valueJSON value
The valueJSON is a JToken, Json(valueJSON) method is serializing your valueJson as a JToken class and not as the deserialized array of objects that you need, you can try to return the JToken as a string with return Content(valueJSON .ToString(),"application/json"); or parse the JToken to the original array of objects.

How to pass the parameter to a method when calling in MVC5?

I have a method defined like this:
public ActionResult MatchedBusinesses(List<Business> businesses)
{
if (businesses != null)
{
return View(businesses);
}
return View("NoMatchFound");
}
Then, in my other method I have something similar to this one:
var list = results.AsEnumerable().OrderBy(b => Math.Abs(Convert.ToInt32(temp) - Convert.ToInt32(b.Zip))).Take(5).ToList();
return RedirectToAction("MatchedBusinesses", "Home", list);
The point is that, for the list variable I get the 5 entries that I select using the query. But, then I want to pass that result to my other method, which will be used in other method's view. The problem is, when I call the other method, the businesses parameter is always null. How can I solve the problem? Clearly, I'm not passing the parameter to my MatchedBusinesses method correctly. Any idea, how to solve the problem?
You are using the overload of RedirectToAction where the 3rd parameter is object routeValues. Internally the method uses reflection to build the route values based on the names and the ToString() values of the objects properties.
It works only for properties that are value types, but for properties that are complex types, including collections, it will not bind because (in your case) the value is a string "List<YourAssembly.Business>" and a string cannot be bound to a collection.
You need to persist the collection before redirecting (e.g. database, session, TempData) and then retrieve the collection in the action result.
For example
var list = results.AsEnumerable()....
TempData["results"] = list;
return RedirectToAction("MatchedBusinesses", "Home");
public ActionResult MatchedBusinesses()
{
List<Business> businesses = (List<Business>)TempData["results"];
}
but use TempData with caution (if the user refreshes the browser, the data will be lost). Its better to persist the information to the database with some key, and then pass the key as a route parameter to the MatchedBusinesses() method so that you can retrieve the data from the database.
Edit
What you're trying to do doesn't make much sense. You cannot, and should not, attempt to send large and/or complex objects, like a List, using Route. Instead you should use POST, or follow Stephen Muecke's suggestion in using TempData
However, here's how you can correctly send simple values using RouteValue
You pass parameters by using
return RedirectToAction("ActionName", "ControllerName",
new { paramName = paramValue });
Or if the target Action it's in the same controller
return RedirectToAction("ActionName", new { paramName = paramValue });
The parameter name, is optional. But using
return RedirectToAction("ActionName", new { paramName = paramValue });
Implies that the target action accepts a parameter with the name paramValue.
Here are all the overloads for RedirectToAction
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirecttoaction%28v=vs.118%29.aspx
Try wrapping your parameter in your return statement in a blank object variable like so:
return RedirectToAction("MatchedBusinesses", "Home", new { businesses = list });
All of the route values for an action have to be one parameter, so it's passed as an object, and then split into the various parameters of the receiving action. Even if you have only one param, it's still looking for an object to split.

How to return Json as part of my view in C# MVC

My question is: How can I combine the two of these action results into one? There really seems no point in having the first one only to do one line. But I cant see a way out. Any ideas would be appreciated. The remaining I provide for background.
I am trying and successful in returning a partial view with the Json results I require but I am using two ActionResults of the same name (one with parameter one without) to achieve this. If I continue in this manner, I will have to repeat all my ActionResults twice. The problem I have with this is that the first action result does nothing more than literally this:
[HttpGet]
public ActionResult MyResults()
{
return PartialView();
}
That is used to return the view. Within the view I have some JQuery/Ajax which in turn calls another action result of the same name but with parameters. This action result effectively populates a Json object which is then parsed and rendered into the view above as a table. Effectively this actionresult does all the work. It looks something like:
[HttpPost]
public ActionResult MyResults(DataTablePrameters param)
{
//Get the full list of data that meets our needs
var fullList = _myResultsRepository.GetListByID(Id);
//Count the records in the set
int count = fullList.Count();
//Shorten the data to that required for the page and put into object array for Json
var result = from r in fullList.Skip(param.iDisplayStart).Take(param.iDisplayLength)
select new object[]
{
r.field1,
r.field2,
r.field3
};
//Return Json data for the Datatable
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = param.iDisplayLength,
iTotalDisplayRecords = count,
aaData = result
});
}
Those of you not familiar with it, will not be aware that I am using DI/IOC and for brevity I have not included the details of this. But that is not my question. Also the above code used Datatables from the following site:
http://datatables.net/index
Which are actually quite good. And again, using all the above, my code works well. So I don't have problems with it. I know its somewhat inefficient because it loads the resultset into a variable does a count, then skip...take and so on but again, it works and this is not my question.
So again my only question is, how can I combine the two of them into one view. There really seems no point in having the first one only to do one line. But I cant see a way out. Any ideas would be appreciated.
Remove the [HttpPost] and [HttpGet] attributes from the ActionResult you want to use.
Check the validity of your fields contain in DataTablePrameters param like :
public ActionResult MyResults(DataTablePrameters param = null) {
if(string.IsNullOrEmpty(param.sEcho) && string.IsNullOrEmpty(param.iDisplayStart) && string.IsNullOrEmpty(param.iDisplayLength))
return PartialView();
//Do something
return Json(...);
}
In your view, you can still use the type:"POST" into your $.ajax() with the url:"/YourController/MyResults" like you already do i supose.
Assuming that the separation of POST and GET access is not desired with just one action left, wouldn't just making "param" optional do the trick?
public ActionResult MyResults(DataTablePrameters param = null) {
if(param == null)
return PartialView();
// Repository action...
return Json([...]);
}

How do I accept an array as an ASP.NET MVC controller action parameter?

I have an ASP.net MVC controller called Designs that has an action with the following signature:
public ActionResult Multiple(int[] ids)
However, when I try to navigate to this action using the url:
http://localhost:54119/Designs/Multiple?ids=24041,24117
The ids parameter is always null. Is there any way to get MVC to convert the ?ids= URL query parameter into an array for the action? I've seen talk of using an action filter but as far as I can tell that will only work for POSTs where the array is passed in the request data rather than in the URL itself.
The default model binder expects this url:
http://localhost:54119/Designs/Multiple?ids=24041&ids=24117
in order to successfully bind to:
public ActionResult Multiple(int[] ids)
{
...
}
And if you want this to work with comma separated values you could write a custom model binder:
public class IntArrayModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null || string.IsNullOrEmpty(value.AttemptedValue))
{
return null;
}
return value
.AttemptedValue
.Split(',')
.Select(int.Parse)
.ToArray();
}
}
and then you could apply this model binder to a particular action argument:
public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
...
}
or apply it globally to all integer array parameters in your Application_Start in Global.asax:
ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());
and now your controller action might look like this:
public ActionResult Multiple(int[] ids)
{
...
}
To extend on Darin Dimitrov's answer, something you can get away with is accepting a simple string in your URL parameter and converting it to an array yourself:
public ActionResult Multiple(string ids){
int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
/* ...process results... */
}
If you get a parse error while doing this (because someone passed you a malformed array), you can cause your exception handler to return a 400 Bad Request error instead of the default, more unfriendly 404 Not Found error that MVC returns when an endpoint is not found.
You can also use this URL format, and ASP.NET MVC will do everything for you. But, remember to apply URL encoding.
?param1[0]=3344&param1[1]=2222
I don't know where Groky's URL string was coming from, but I had the same problem with some javascript calling my controller/action. It would build up a URL of null, 1, or many "IDs" from a multiple-select list (which is unique to the solution I'm going to share).
I copy/pasted Darin's custom model binder and decorated my action/parameter, but it didn't work. I still got null valued int[] ids. Even in the "safe" case where I actually did have many IDs.
I ended up changing the javascript to produce an ASP.NET MVC friendly parameter array like
?ids=1&ids=2
I had to do some silly stuff, though
ids || [] #=> if null, get an empty array
[ids || []] #=> if a single item, wrap it in an array
[].concat.apply([], ...) #=> in case I wrapped an array, flatten it
So, the full block was
ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')
It's messy, but it's the first time I had to hack like this in javascript.
.Net Core Answer
For those coming here in recent times, you can do this in .Net Core with:
http://localhost:54119/Designs/Multiple?ids=24041&ids=24117
and:
public ActionResult Multiple([FromQuery] int[] ids)
{
...
}

How to bind a jQuery object containing strings to List<string>?

This is hopefully a one liner.
I've read Phil Haack's article http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx and other questions, but those are about <form>s and using multiple names, rather than formatting a JS object for a $.ajax() request.
I have:
var elements$ = $('.someClass');
if(elements$.Length === 0){
//no need for call to server if no elements on page
return;
}
var elementsList = elements$.map(function (i, element) {
return $(element).data('some-data-attribute');
})
var data = getOtherObjectContainingData();
//encode in a format that can be automatically bound to list
data.ListOfString = elementsList.get().serializeArray(); //THIS LINE
$.post("ControllerName/ActionName", data, handler);
with controller action
public JsonResult ActionName(SomeObject OtherObject, List<string> ListOfString)
I have tried serialize(), serializeArray() and can solve this with a CSV string, but I don't want to faff about with it if the Model Binder can automatically do it if the request is formatted correctly.
How do I go about binding $('string', 'string', 'string') properly?
Create ListOfStrings as an array, then extend it as an object
data.ListOfStrings = $.extend({}, ListOfStrings);
Should do the trick but obviously I have no way of telling ;)
Have you tried .toArray() ?
var elementsList = elements$.map(function (i, element) {
return $(element).data('some-data-attribute');
}).toArray();
The .map() method returns a jquery array, calling .toArray() turns it into a pure javascript array.

Categories

Resources