ASP.NET MVC, JSON post to controller action with FormCollection parameter - asp.net-mvc

I have a bunch of controller actions mostly used for saving data to backend storage. For now most of them use a signature like this:
//
// POST: /WidgetZone/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
as you can see, it accepts FormCollection. This works fine with classic user views. Now I want to JSON- enable these actions. And I do it using JsonPox action filter like this:
//
// POST: /WidgetZone/Create
[JsonPox]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
Will this work when the action expects FormCollection?
For instance this work without issues (of course I construct Json object in my JavaScript client-side to pass it into this action):
//
// POST: /WidgetZone/Create
[JsonPox]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(string id, string description)
It is all about a task of converting postback UI into asynchronous one, so that saves and updates would be done async. Am I on the right track? I do think that developing separate Json, XML or classic ViewResult actions is not the best way to go.
Help appreciated

This filter is based on the the OnActionExecuted method which is run after the action method is executed in order to JSON or XML serialize the returned model. What you have as input to your action method is not important. Once the action finishes execution the filter will look for the model that you stored in the ViewResult and serialize it according to the Content-Type header that's passed in the request.

Related

MVC detect when model is empty

I'm new to MVC, so I'm trying to figure out some best practices.
Suppose I have a controller HomeController method Index(MyViewModel model):
public ActionResult Index(MyViewModel model)
{
//if loading the page for the first time, do nothing
//if the page has been posted data from somewhere, then I want to use
// some of the arguments in model to load other data, like say search results
}
When I navigate to the /Index page, I (myself) expect the model object to come through as null, but it doesn't. MVC (somehow) creates a MyViewModel for me.
My question is, what's the best way or most consistent to determine if model was created automatically, or via a post?
Ideas:
Create a property on MyViewModel that gets set when the view is posting back
Check for if the Request.HttpMethod == "GET" or "POST"
Something else?
You should use different actions for your GET and POST requests. Don't try and make a single method do too much.
[HttpGet]
public ActionResult Index()
{
// handle the GET request
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (ModelState.IsValid)
{
// it's a post and the data is valid
}
}
The correct method will then be called depending on whether it's a GET or POST
Create two actions, one which accepts a model instance and one which doesn't.
Even though you're "going to the same page" you are in fact performing two distinctly different actions. The first action loads an initial page, the second action posts some value to be acted upon. Two actions means two methods:
[HttpGet]
public ActionResult Index()
{
// perform any logic, but you probably just want to return the view
return View();
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// respond to the model in some way
return View(model);
// or return something else? a redirect? it's up to you
}
Note that this kind of breaks your restful URLs. Consider semantically what you're doing in these actions:
Viewing an index
Posting to an index
The first one makes sense, but the second one probably doesn't. Normally when you POST something you're doing something related to a model or action of some sort. "Index" doesn't really describe an action. Are you "Create"-ing something? Are you "Edit"-ing something? Those sound like more meaningful action names for the POST action.

Overloading in MVC

I read here that I can't overload actions in MVC because of routing confusion
I tried to overload Index() in HomeController and I got the exception as article said, but I noticed that
microsoft has overloaded the actions in AccountController
public ActionResult Login(string returnUrl){}
public ActionResult Login(LoginModel model, string returnUrl){}
Please need clarification, thanks
Microsoft has overloaded this by setting HttpGet and HttpPost. One for GET request and another for POST request. What about your code?
[HttpGet]
public ActionResult Login(string returnUrl){}
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl){}
Till today you cannot overload your controller's Action method with same name but different parameters.
The only possibility is to have two overload, and for that you need to set the method's property to HttpGet and HttpPost. For example
[HttpGet]
public ActionResult foo(string myString)
{
return View();
}
[HttpPost]
public ActionResult foo(MyViewModelClass object)
{
return View();
}
And regarding your confusion,
From general convention, first method should be of type Get which gets called when someone sends request to access that page.
Second method is called when user submits a form with his login details.
In AccountController first method works with GET method, second with POST one. It was realized by attribute [HttpGet] and [HttpPost].
Read more about get and post here.
In addition to above answer we can add name attributes along with HTTPGET and HTTPPOST as
[HttpPost]
[ActionName("Edit")]
public ActionResult Edit_Post(some parameters)
{
//code over here
}
After this we can call it as :- /MVC/EmployeeController/Edit/1
Some definitions first:
Overloading is a form of polymorphism, in particular an interface, in the sense of a class publicly visible part, related one.
When we speak about inheritance we mean overriding.
Action is a segment of a URL.
Back to your question...
It is the ControllerActionInvoker which is responsible for finding the method to which an action is mapped. Given GET and POST we see polymorphic methods in a class mapped to the same action, but serving different HTTP methods (any action, that is, URL segment polymorphism here?!). And again yes, we may use ActionNameAttribute (MVC v5) to map an action to a class method, but again, this has nothing to do with any sort of polymorphism. Simply put, all that happens is in the ControllerActionInvoker and has nothing to do with overloading or overriding, and finally with any sort of polymorphism -- it is just mapping.
Conclusion.
A simple question arises:
What in a string (a segment of a URL, 3.) relates to any one of the OOP definitions (1. and 2.) above? Or, in other words, can any of the OOP concepts above be transformed to a (part of a) string?
The fact that a transformation between URL segment, which happen to be called "action", and a class method exits does not imply that all we know about the first mechanically can be applied to the second and vice-verse. The question is misleading and its main intention is to confuse someone, not to test his/her knowledge (I suspect that this is an artificial interview questions, not a real one).

Process get and post

I have an question about the get and post process in ASP.NET MVC 4.
I'm sure that often talk about but it isn't easy to search for this topic.
Let me try to explain:
I start my controller with the standard method:
[HttpGet]
public ActionResult Item()
So, in this function I retrieve a lot of important data as example the user id and so on.
In my case, I even collect data in my viewbag() to decide if a form has to be displayed or not.
Now, if I start a post back:
[HttpPost]
public ActionResult Item(FormCollection formCollection)
the function gives as standard View() back.
The Problem is now, that after the post method, the business logic (retrieve user id and so on) of the GET method isn't called... I have tried to solve it with
return this.RedirectToAction("Item");
but is that really the solution for repeat the logic out of the start (get)? And how can I give the new values from the post method to the get method?
Best regards,
Patrik
That pattern is called Post/Redirect/Get.
To pass additional data to GET method you can use TempData and ModelStateToTempDataAttribute from MvcContrib - it passing ModelState to tempdata if Redirect is returned and tempdata to modelstate if View is returned.
[HttpGet]
[ModelStateToTempData]
public ActionResult Item(int id)
{
// prepare view
return View();
}
[HttpPost]
[ModelStateToTempData]
public ActionResult Item(FormCollection formCollection)
{
// do some business logic
int id = service.DoBusinessLogicAndReturnSomeId();
return this.RedirectToAction("Item", new { id });
}
You should avoid to have business logic in GET. All business logic should be inside POST method and after you invoke that you can redirect to GET where you prepare your view.

How to Store large data in MVC4

I am new to MVC.I am having some doubts so please clarify me.
How to store large data in MVC4 and how to pass that data across the pages.
How to maintain user details across the pages. In webforms we are having sessions but in mvc4 how we will do.
if we are having two actionresult of same name one will be fired on POSt action. How the CLR identifies which Action method to be called..means how it will identify that POSt method is called.
Define "large data" - remember that the web is stateless, persistence is done using a database or a server-side cache. I need more information about what you want to accomplish here.
ASP.NET MVC still supports Sessions. You can access the Session collection from any Controller action.
The Post action method must have a different method signature. The usual approach is to specify the view's model as a parameter, or a FormValueCollection, for example:
-
// GET
public ActionResult Foo() {
}
// POST
[HttpPost]
public ActionResult Foo(FooModel model) {
}
OR:
// POST
[HttpPost]
public ActionResult Foo(FormValueCollection postValues) {
}

Using a ModelBinder to get an object by an ID

I have multiple controller actions that takes an id
public ActionResult Get(int? id) {
...
}
public ActionResult Delete(int id) {
...
}
public JsonResult GetJson(int? id) {
...
}
I'm thinking its best practice to use a ModelBinder (SomeObjectFromIDModelBinder) on each action, so the obtaining of the object is separated from the controller, and keeps the action methods smaller.
The reason I don't want it to be called SomeObjectModelBinder is because I also have a need to recreate Models from JSON, so have a SomeObjectFromJsonModelBinder which handles recreating the 'SomeObject' from a JSON string.
I'm thinking this is a suitable usage of ModelBinders (naming convention), but just wanted clarification. Thoughts?
You don't need to do anything to get the ID. THe MVC handler will look for simple values of the same name as the method parameters in the Form data, the Query String, and the Route.
So you could have a route /{controller}/{action}/{id} with defaults of action="Get", id=1.
then the id could be specified in the URL as either /Home/Get/3 or /Home/Delete?id=6.
Alternately, you could have a textbox with an id of "id" and a submit button in a form that posts to "/Home/Get".
ModelBinders are intended to allow you to have action methods that are classes by creating the instance and populating the properies from the Form data, Query string, or Route data.
I've decided that it is acceptable to do what I was asking, and having multiple ModelBinders that will bind different data to a Model.

Resources