In mvc the page is not get post back as in asp.net then how can we perform postback operations in asp.net mvc2. for ex how to perform particular action when someone selects a chech box?
Thanks in Advance
The mechanism behind the postback model in WebForms is called HTTP POST. This is how user input is communicated back to the server.
You can do it manually. Attach a JavaScript handler manually to the checkbox "onclick" event and perform a POST request to some url. There, this request will hit some controller action where you do what you want. For example, update the model (check/uncheck the checkbox) and return the same view from which the POST originated. The view will now show the different state for the checkbox.
The WebForms mechanisms do pretty much the same, though these things are abstracted away from you. With ASP.NET MVC you'll need to learn how to do it on your own (which is always a good thing).
Your MVC Action method on your Controller somewhat is your 'PostBack' handler.
Start with a simpler example; a simple HTML form post:
<form action="/MyController/MyAction" method="post">
<input type="text" name="myName" />
<input type="submit />
</form>
Now in your controllers action you can get the posted values and perform your tasks. When done give the browser back what it needs:
public class MyController: Controller
{
public ActionResult MyAction(string myName)
{
// Do something with myName
return new ContentResult { Content = "Hello " + myName };
}
}
As for a checkbox, it is different. You need to learn Javascript (jQuery is the most used library to use with that) and post the action using that. For example you can wire up to the check box 'onclick()' event and perform an XHR - a browser specific Javascript operation, post (you can use jQuery for that too) to your controller.
So you need to start thinking differently than webforms abstractions and get involved with HTML, HTTP and Javascript.
you can Put this inside an MVC Razor page:
if (Request.HttpMethod=="POST") {
}
Related
ASP MVC WebGrid renders pagination links like
http://host/AnyController/AnyAction?Length=4&page=1
Any chance to parametrize or customize this to
http://host/AnyController/AnyAction/1
to conform better to MVC routing conventions?
(NOT important: btw Length is redundant. If the controller's Action method does not know the page length, by heart that's problem. )
Thanks in advance
One way to handle your default route conflict can be this, as most of the time when you use you route it will hit the action method without the [HttpGet]. All you need to do is a GET, whenever you sort or page the web gird, it will try to get data and hit the a HttpGet Action, this will work as follows:
[HttpGet]
public ActionResult YourActionMethod()
{
return PartialView("YourView",YourModel);
}
The best part is, upon sorting, the request will send a parameter named as "sortBy" too, you can use this here and decide what you want to do with the binded Model with the grid. You can inspect what URL the Sort header will hit by using the "Developer Tools" in your browser. You can use this action do as you will,
Note : By default the action method it would be hitting would be same as the controller name.
So far:
I have a page with multiple submits on it, where each submit depends on the previous one.
The same page is rendered each time a submit is clicked.
I found myself writing spaghetti code in the controller method (branching based on the ViewModel), and wanted to factor out the behaviour for each submit into a separate method.
I implemented the solution found here - specifically the solution posted by mkozicki based on the article by Maartin Balliauw.
This worked well for forking to different controller methods. But I encountered two problems:
Returning to the same view each time.
Hard-wiring the action method names in the View.cshtml
Here's the code:
Controller:
public class PlayerStatController : Controller
{
public class PlayerStatViewModel . . . //quite complex ViewModel
// HTTP GET
public ActionResult SelectPlayer()
{
List<string> idx_list = getSeasonIndex();
return View(new PlayerStatViewModel(idx_list));
}
// One of three forked action methods
[HttpPost]
[MultipleButton(Name = "action", Argument = "ChosenSeason")]
public ActionResult ChosenSeason(PlayerStatViewModel viewModel)
{
List<string> team_idx = getTeamNameIndex(viewModel.selected_seasonIndex);
return View("SelectPlayer",new PlayerStatViewModel(new List<string>(), team_idx, new List<string>(), 0));
}
Here an excerpt from the view (SelectPlayer.cshtml)
<form action="/PlayerStat/ChosenSeason" method="post">
<fieldset>
<legend>Select Season</legend>
<div class="editor-field">
#Html.LabelFor(m => m.selected_seasonIndex)
#Html.DropDownListFor(m => m.selected_seasonIndex, Model.seasonIndex_select_list)
#Html.ValidationMessageFor(m => m.selected_seasonIndex)
</div>
<p>
<input type="submit" value="Choose Season" name="action:ChosenSeason" />
</p>
</fieldset>
</form>
Hence:
Is returning from the forked action method with return View("SelectPlayer",new PlayerStatViewModel(...); the best solution to forcing the same view (SelectPlayer.cshtml) to be rendered every time?
Is there a way to avoid hard-coding the action method name in the View (i.e., <form action="/PlayerStat/ChosenSeason" method="post">) I would like to keep using #using (Html.BeginForm()) if possible.
Specifying the view name in the return statement is the best and most practical way to return a view that is named something different than the current action method being executed. I believe this is by design in order to decouple action methods from a single view.
Again, for the view if you want the form to post to an action other than the one specified in the current URL you have to specify it explicitly. Using an empty BeginForm() will cause the form to post to the same URL that was returned on the previous request.
I believe what you have is the best way to tackle the problem and is the way I have my MVC application implemented as well. There is nothing wrong with being explicit, especially when it comes to views and view logic because they are by their very nature explicit. Separating the different submit buttons into different action methods is a solid approach and one that will inherently require you to specify which action to target for each submit button. You can think of this approach as analogous to Web Forms Server Side Event Handlers for button clicks (minus all the nasty page life cycle). This approach is elegant and clean, only the server side code corresponding to the submit is executed.
May be this sounds very stupid question but I'm a student who just came to know about MVC and I find it very interesting. Also, I have very little or no knowledge about Ajax and jQuery. I have been creating some basic applications like posting a comment or a blog post without using Ajax services or jquery. Now I've come to a part where I see Ajax services being called and custom jQuery code are being written.
Let us consider a small example where one can add comment on the main page and after the comment being written and submitted, it appears on main page.
Imagine a controller with following functions
public class CustomAjaxController : Controller
{
//
// GET: /CustomAjax/
private static readonly List<string> Comments = new List<string>();
public ActionResult Index()
{
return View(Comments);
}
[HttpPost]
public ActionResult AddComment(string comment)
{
Comments.Add(comment);
return RedirectToAction("Index");
}
}
I know using list of string to store the comments is not good idea but for the sake of simplicity and to explain my point I've used it. Also I don't have model but again for same reason.
#model IEnumerable<string>
<h4>comments</h4>
<ul id ="comments">
#foreach (var comment in Model)
{
<li>#comment</li>
}
</ul>
<form method="POST" id="commentsForm"
action = "#Url.Action("AddComment")">
#Html.TextArea("Comment", new{rows =5, cols =40})
<br/>
<input type ="submit" value="Add comment"/>
</form>
Now, I've seen same thing being done using jquery and ajax requests. But why should i do it to achieve same result, or how do I know this is the right place to use ajax requests.
But why should i do it to achieve same result, or how do I know this
is the right place to use ajax requests.
AJAX offers a couple of benefits:
It saves bandwidth because only the portion of the page that you want to be updated actually is sent over the wire. In your sample code you are reloading the entire HTML even if only one comment is added on a single place
It is asynchronous meaning that the user can do other things on the page while waiting for the server side processing
You can use it whenever you want to take advantage of one of those things.
In my layout I'm using RenderAction that will output a simple email form which will post to an action.
// In _Layout.cshtml
#{Html.RenderAction("Email", "Home")};
// Home Controller
[ChildActionOnly]
public ActionResult Email(){}
[HttpPost]
public ActionResult Email(params){}
Now the RenderAction works great when it's the only form on the page. If it's not, however, the Email Post action gets called in addition to the other form action which I don't understand. The forms are not nested; the source looks something like this:
<form id="email-form" action="/home/email" method="post">
// form elements
</form>
<form id="some-other-form" action="/somecontroller/someaction" method="post">
// form elements
</form>
How can I avoid the post of the child action when it comes from a different form? As a workaround I can check the paramaters passed in and if they're null I should be fine and dandy, but I don't think this is the intended behavior.
this.ControllerContext.IsChildAction; in your controller will give you the ability to check if the post is coming from the URL or through a Html.RenderAction.
That might help you debug it a little better.
So normally I have links like:
http://domain.com/action?some=1&foo=2
and so on.
It's make me really upset, as some clever users might just reinvent link on their own and get access to some data, which is not desirable. I know i can setup security On server side, but i'd like to make links look like:
http://domain.com/action
And 'some' and 'foo' send like POST request
Actions in ASP.NET MVC don't distinguish betweed Post and Get as far as the parameters to the actions are concerned. However, you can start by marking your actions with the attribute [HttpPost]. This will limit the request options to post only.
Now to the second "issue", you need to change all your links so that you use post instead of get, you can do this by using ajax, check out $.post in jQuery for that.
This doesn't solve any security issues with your parameters though, it generally doesn't matter if you show it in the querystring or of it is sent by a post. If someone wants to inject something into your post-data, it's not rocket science.
You have to wrap it in a form for it to work; with the inputs being hidden. On the server side you have to restrict the action to only responding to a POST request. However, this doesn't really solve your problem as a sufficiently interested and knowledgeable user can just as easily craft a POST as a GET.
You can add form to the view and apply [HttpPost] attribute for the action which will take the model after the post.
Adding form to the razor view (also you will need a button or a link to sumbit):
#using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Post, new { #id = "someFormId" }))
{
#Html.HiddenFor(model => model.some)
#Html.HiddenFor(model => model.foo)
}
And here is a Controller with action to proccess your post:
public class SomeController : Controller
{
[HttpPost]
public ActionResult SomeAction(SomeModel model)
{
//process 'some' and 'foo' here
return View(model);
}
}
To enhance security you can easily encrypt/decrypt "some" and "foo" values.