In ASP.NET MVC 3, which is more correct to use: Json() or new JsonResult()? Either returns the same result. Thanks for helping solve an office debate.
Json() is just an extension method that actually returns a JsonResult object behind the scenes (rather than needing to call the constructor directly).
I almost always use the Extension Method myself. This keeps more in line with the other common return types from Action Methods like View(), PartialView(), etc.
I also make sure to create an extension method for any custom ActionResult types that I create. In the end it's a matter of personal preference.
If you a returning a large dataset as a data source for grid or other UI controls via Ajax, sometimes if this dataset is over 1000 records UI controls will not bind because of maximum Json length is not specified.
So instead of
return Json(data),
you can do this: return new JsonResult(Data = data, MaxJsonLength = 50000);
Related
I am trying to build sth pretty simple, but I try to do it the correct way. But I struggle to figure out what is best.
I have a process chain where the user has to fill in some fields in different forms. Sometimes it depends from the user inputs which form the user is shown next.
[HttpGet]
public IActionResult Form1(Form1Vm f1vm)
{
return View(f1vm);
}
[HttpPost]
[ActionName("Form1")]
public IActionResult Form1Post(Form1Vm f1vm)
{
//process the data etc
//prepare the new viewmodel for the next form view (f2vm)
//Option1:
return View("Form2", f2vm);
//Option2:
return RedirectToAction("Form2", f2vm);
//for Option 2 I would need an additional HttpGet Action Method in which I
//would have to call Modelstate.Clear(); in order to not have the
//immediate validation errors on page load
//also all the properties of my viewmodel are passed as get parameters
//what looks pretty nasty for me
}
//More form views action methods should be added here...:
What is the better way? As mentioned in my comments above I have quite a big disadvantage for using the RedirectToAction option. However if I use the direct View(); call, I don't take care on https://en.wikipedia.org/wiki/Post/Redirect/Get and the user cannot simply refresh a page without getting a warning that his form is submitted once again.
Do I miss another way or don't see something obvious?
Edit: I just thought about a 3rd way, which I have seen quite often: Not transfering the whole VM to a HttpGet method but only the ID. I'd then have to load all the data stored previously directly from the db, map it again to my new VM and then call the View(); with this VM. Right now I think this is the "best" solution, however I feel like it is pretty laborious...
As per the dicussions, I would suggest using depending on your preference :
1) Save to db at the end of each form post and as you suggested use the I'd to redirect to a GET.
2) Depending on the the number of form pages and your requirements, retrieving values that a form needs on the get would be standard practice. This ensures that if a user drops off a form at any stage you can then start them off where they left off.
3) I wouldn't setup the viewmodel for the next form in the post of the previous. Generally as part of the single responsibility principle you want to ensure that your methods have only one reason to change.
4) PostRedirectGet pattern should be implemented with this to ensure data is not saved multiple times if a user refreshes after a post.
I just came across this topic in a current project and I would like to know the best way to handle the "problem" of objects getting lost, when using the HttpPost method when submitting a form. Thoughout the web and the posts on stackoverflow I gathered some ways to deal with it.
So, once I got that a view model gets objects or lists from the HttpGet request they are lost because of the stateless nature of http. I now have seen different approaches to get that objects back when passing the view model back to the view.
Store objects in hidden field
#Html.HiddenFor(m => m.Object)
This seems to be working fine if the view models property is serializable. But what if there is logic behind the objects? Will this work for all scenarios? And on the other hand, I don't want every object inside my view model, just the ones for display and the user can interact with.
Get the object via AJAX and HelperMethods
#Html.Some3rdParty().ComboBoxFor(m => m.List)
.DataSourceUrl(#Url.Action("GetComboSource"))
[ComboBoxSource]
public ActionResult GetComboSource()
{
var data = Service.GetStaticSource();
return Json(data);
}
Using 3rd party libraries like Kendo UI MVC I can easily put a .DataSourceUrl() HtmlHelper on my control for requesting a controller to provide the datasource. Or just using jQuery's $.get() method. The problem is: What if I can't use such a library or the requirement says, that JS has to be avoided as much as possible?
Get the object back in the HttpPost Controller action
[HttpPost]
public ActionResult Edit(ViewModel viewModel)
{
var tempViewModel = Service.GetViewModel(viewModel.Id);
viewModel.Object = tempViewModel.Object;
return View(viewModel);
}
This one seems a bit brittle to me. On the post action I have to call whatever service provides the view model, extract certain objects and attach them to my recieved view model.
Currently that's all I can think of, but in short:
I'd like to know, what is the best practise to handle it throughout a project and what's the best way for maintainability?
For me it seems there is no perfect solution so far. How do you do it in your projects?
Avoid solution 1: you will weigh your requests, the data can be forged and if your object is not serializable (or the to string method does not provide useful string) you will have some problems. If you want to use something similar prefer Session
Solution 2: I use ajax populating when the input have to be filtered depending of other controls value. If it is not the case you will have controller with lot of actions and not easily maintanable.
Solution 3 is the one I use and I prefer because it is more DRY, more secure (no forgery), and keeps the controller light.
Just change
<input class="ui-input-text " type="text" id="PlateNo" tabindex="2" name="PlateNo">
to
<input class="ui-input-text " type="text" id="PlateNo" tabindex="2" name="PlateNo" value="#Request["PlateNo"]">
You can be show on the textbox sending value for this input.
Only add value="#Request["yourinputname"] to your input.
So somebody asked me the question:
When would I return View() and when would I return PartialView()?
My immdiate reaction was, if it's a patial use PartialView(). Then I realised that I have quite often returned View() for a partial view with no, apparent, detremental effects?! So what's the point in the return PartialView() call?
I found this question What's the difference between “return View()” and “return PartialView()”. This appears to be particular to MVC2. i.e. talks about .aspx and .ascx control extensions. Using Razor all our views are .cshtml whether they are partial or not.
Which got my thinking is the PartialView() just a hangover from MVC2 and not really relevant in MVC3+ (When using Razor anyway)? Or am I missing some crucial feature of PartialView()?
tl;dr: PartialView() does not use a layout for the view being returned.
You can set a default layout file within _ViewStart.cshtml (located in the Views folder) which will then be used by all views. By doing that, you avoid having to set the Layout property within each view. PartialView() will not include that layout file or any other.
If you want to return a partial view, e.g. in a child action called using #Html.Action(action, controller), use PartialView. If you want to return a "full" view including the layout, use View().
MSDN Reference:
If you contrast the MSDN definition for ViewResult() Object with the MSDN definition for PartialViewResult() Object
you find the only difference is that ViewResult has an extra property:
public string MasterName { get; set; }
Otherwise, both Objects inherit from ViewResultBase and seem to inherit all other properties and methods from the base class.
Unfortunately, the implementation of the abstract method ExecuteResult() is not published, but I have no doubt it uses the MasterName field to find and render the Master Layer.
Our shared experience:
Just like you, I have returned partial views =using View(). I don't recommend it. But the apparent difference isn't big.
It does seem a touch wasteful to have an extra object just for MasterName, but the more important difference is probably the implementation of ExecuteResult().
When you choose View() method and create a ViewResult Object rather than using PartialView() to create a PartialViewResult Object, you are being less efficient; your application is doing the extra work of checking if your MasterName field is assigned.
I need to get some Json to the client side from the server and it's somewhat troublesome as almost all tutorials assume an Ajax call to a separate action to get the Json.
This led me to think that there must be some reason why it is done this way. In Asp.Net MVC we can pass a Model along with the view to get the information but we can't seem to easily pass a Json object. Instead you are supposed to make a separate call to get this information.
What if the Json info is known when the page is generated, why not generate it at the same time?
I'm sorry if I wasn't clear enough. While it's nice to hear of ways to get Json to the client, the question is actually whether there is a specific reason the Ajax call method is much more popular, like security or anything like that.
Can you put something like this into your view? (rough pseudo code, assuming using a Razor view)
< script >
var myJSON = { Field: #model.Field, Field2: #model.Field2 };
< /script >
Because you do not need both at the same time... on the first call will be to get html (the view of the data - represented by a view model), and any ajax calls will be to get the possibly updated data (json serialized view model).
No reason why you can't. You could use the javacript serializer to create a JSON string that drop on the page. You could also create an action that return the json string that you called from a script tag.
What you want if you're using KnockOut, would be the Mapping plugin that turns an ordinary JS object, like that generated above, into an observable ready for KnockOut to use. See here from info. http://knockoutjs.com/documentation/plugins-mapping.html
You can use content-negotiation by setting accept header. This is considered a best practice (and according to some RESTful).
This needs to be supported and implemented at server as well. ASP NET MVC does not make it easy to support content-negotiation and you have to implement it yourself by if-else or using ActionFilter and implementing action selector.
i wish to have a simple Action in my controller that accepts a few optional values and some integer values.
this is my route i wish to have:
HTTP.POST
/review/create
and this is the Action method i would like...
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Create(int userId,
int addressId,
byte baseScore,
byte reviewType,
string subject,
string description)
{ ... }
I'm under the uneducated impression that all of those arguments above will be populated by the forms collection values ... but it's not happening. Also, I have no idea how I would write a route, to handle those ... because those values are form post data....
here's my global.asax....
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Api - Search methods.
routes.MapRoute(
"Search Methods",
"{controller}/{action}"
);
In fact, the action method is never called because it doesn't seem to find it :(
But, if create and action without any of those arguments, then it finds it ?????????
How would you write a route and action method to accept some require and some optional arguments, for the route /review/create ?
As far as i can see you may rewrite your controller action like this:
public ActionResult Create(int foo, int bar, byte blah, string name, int? xxx) {
// code here
}
The ModelBinder will then ensure that foo,bar and blah are set. Name and xxx may be null. I can't test it a the moment, but i think return type of the action should be ActionResult.
If you are POST'ing a form, just make sure that the elements in your form (textboxes, checkboxes, textarea, etc) have id's that match the parameters in your method. As an alternative you can pass a FormCollection to the method, and do myFormCollection["foo"] to get a string representation of the value (which can then be parsed to an int).
From my experience, you are missing a number of key elements and concepts with this question.
First and foremost, I don't believe you can execute a POST without a form. The form has to contain the controls from which you pull the values that get passed to the controller method. If the goal is to simply unit test your POST controller method, then just call the method directly in your test, which it appears that you're doing, based on one of your comments. If you involve the view, then you're doing integration testing, not unit testing. Regardless of the test type, the test will always fail because you are choosing not to build the form. Even if you manage to force the POST using Fiddler, Firebug or any other mechanism, you're still not testing the view, you're testing the HTTP protocol.
I highly recommend that you employ a web application testing tool, such as WatiN or Selenium, to test your web pages, rather than throw together a quick-and-dirty test that really doesn't test anything useful.
In your post request set content-type="application/json; charset=UTF-8" and pass the values for the method parameter in JSON format. This should make Asp.MVC not to look in FormCollection for those values.