How can I use Html.ValidationSummary with Ajax.BeginForm? - asp.net-mvc

I have an AJAX form that I am creating in my MVC project. If the form is submitted using normal browser function and a page refresh occurs I get validation information rendered in the form (the built in MVC validation based on ViewData.ModelState).
Is there a similiar validation mechanism for AJAX forms?
<% using (Ajax.BeginForm("Create", "GraphAdministration", new AjaxOptions()
{
OnSuccess = "newGraphSuccess",
OnFailure = "newGraphFailure",
HttpMethod = "POST"
}))
{ %>
<!-- some form stuff in here !-->
<% } //end form %>

It really depends on where you are getting the content from to display once the form has been posted. The Validation summary is performed created on the server so that is where you have to do the work.
As an example I was using some partial content in an .ascx file to render a form. You get the form in the page the first time round by calling the action directly with Html.RenderAction
You would have your Ajax.BeginForm etc. in the .ascx file. Then call it directly in an action.
When the Ajax call is made from the browser you get it to post to the same action. That way you can do all of the server side validation that you would normally. You should set up the Ajax call to replace the original form with the new html that is returned by the action.
One thing that you have to be aware of is that the replace JavaScript will replace the content of an element not the element itself so remember to us the id of a surrounding element.
Apologies if that is a little convoluted, if you want more details just comment and I'll flesh out the relevant bits.
Extra Detail:
All of this assumes that you are doing all of the validation on the server.
You are going to have a View that has all of the page stuff in it and then some partial content in a .ascx file, this is where your ajax form lives, it needs to be set to replace content by id. Its easiest if it has the same name as the action your ajax is going to call.
You can use Html.RenderAction to get it into the View. You can also pass in data with other versions of the same method. Your essentially calling it in the same way your ajax code will.
You will need to wrap it all in a div with an id set. Use this id in the partial as the content to replace.
When you render the page the html for the form and all of the ajax stuff will get put in.
When the ajax action is called the partial content will be returned with any validation performed. It will replace the content of the div that you gave the id to.
You can have different versions of the action by using [AcceptVerbs(HttpVerbs.Get)] and [AcceptVerbs(HttpVerbs.Post)] attributes
The main problem with this method is that its not self contained, the div with the id is external to the partial.

Related

Using Link inside asp.net MVC4 PartialView to call and pass parameters to an action method and render another PartialView

Within a study course project, I have an MVC PartialView called _item, and inside it I put an href link (<a href = '#Url.Action("AddToShoppingCard", "Home", Model)'>) to call and pass parameters to an Action method (AddToShopingcart) in the Home controller which in turn renders another PartialView (_Footer) in the main _layout.
Although I could do that, but the problem is that when I click the ActionLink, it throws me outside the main _layout and displays only the _Footer content in the browser.
You could use an AJAX link instead:
#Ajax.ActionLink(
"Add to shopping cart",
"AddToShoppingCard",
"Home",
new AjaxOptions {
UpdateTargetId = "someDivYouWantToUpdateWithThePartial"
}
)
The Ajax.ActionLink helper will generate a normal <a> tag with the exception that it will add some HTML5 data-* attributes to it that are interpreted by the jquery.unobtrusive-ajax.js script (that you need to include to your page) and which will AJAXify this anchor. The AjaxOptions allow you to specify some properties of the AJAX request such as for example the id of some DOM element that you want to be updated when the AJAX request succeeds. In your case that could be some div that will receive the PartialView returned by the controller action that is being invoked with AJAX. This way only a portion of the page will be refreshed and the browser will not navigate away from it.

Signal event completion asynchrounously after a POST request to a view page

I have a ASP.NET MVC application which has a view populated with a model which needs to retrieve some data from the user. Besides that, I also have a hidden div tag which contains more information but it should be visible only after the model was sent to the controller on a POST request and after it has processed the information from the model it should change the div tag to visible. Is some way to signal the view that the request was processed and render visible the div tag, remaining on the same page. I believe this is similar to a partial postback from ASP.NET.
Thanks,
Tamash
Yes that's possible via some AJAX functionality. I'm using jQuery in my example:
$.post('Controller/Action', $('#formId').serialize(), function() {
$('#yourDiv').show();
});
This uses jQuery to post the data contained in a form with the HTML id 'formId' to a URL 'Contoller/Action' and shows the div with id 'yourDiv' in case the AJAX request finished successfully. The call $('#formId').serialize encodes the form elements in HTML form with id formId for submission in the AJAX request.
More on jQuery and AJAX here

View Master Page and PostBack

I have a dropdown list on my master page that needs to postback after being changed. After the postback, whatever page initiated the postback needs to be re-displayed.
My question is where do I handle this? Obviously I do not want to have to modify every Action in my project... My guess is to maybe postback to some other fixed action and have that action redirect back to the page that is the referrer. Am I correct? Any thoughts?
Thanks.
Jason
In Site.Master, I ended up wrapping the dropdown within its own form that posted back to a dedicated controller/action.
<% Using Html.BeginForm("ChangeRole", "Home")%>
<div id="roleSelector">Change Role: <%=Html.DropDownList("Role", DirectCast(ViewData.Item("Roles"), SelectList), New With {.onchange = "this.form.submit();"})%></div>
<% End Using%>
In the controller I used the following code to change the mode and then redirected back to the referring URL.
<AcceptVerbs(HttpVerbs.Post)> _
Public Function ChangeRole() As ActionResult
Me.CurrentUser.SetRole(DirectCast([Enum].Parse(GetType(Models.ApplicationRoles), Me.Request.Item("Role")), Models.ApplicationRoles))
Return Redirect(Request.UrlReferrer.ToString())
End Function
I am unsure if this is the recommended way but I have been unable to think of another solution.
When you post back from the dropdown list change what are you doing? Can you maybe handle this in a jQuery call thus eliminating the need to re-display the page at all?
Calls to Action Methods can be asynchronous as griegs says, as such, you can post whatever information you need from the radio buttons to an action method without needing to reload the page.
If you need to update a part of the page, you can replace it with the contents of a rendered action method. If you use the jQuery ajax methods, you can post specific information to your methods.
For example, something like this:
$(document).ready(function()
{
$("#myRadioButton").change(function()
{
//Post to your action method, with the value of the radio button, function to call on success
$.post('yourActionMethodUrl', $(this).val(), function()
{
//Update some part of the page
});
});
});
This is based on memory, so you may need to check the syntax.

ASP.NET MVC Catching 'Save' POST with RenderPartial

I have a asp.net mvc page which renders a record from a database, it uses RenderPartial to call another view which renders an editable list of items related to that record.
My problem is I want a since save / submit button which not only saves changes made for that record but also changes made in the RenderPartial part... I have created a method accepting POST in the RenderPartials controller but it doesn't get called? Any ideas? Or am I using RenderPartial wrongly? I did it this way so that I have a controller that handles the subset of data
Update:
I don't think I've been clear enough:
Imagine a situation where you have a page that is filled with information from lots of different tables in a database... for example imagine you have a record of a person, and then you have all the links they have to Organisations that you want to list on the page, so the page contains:
Individual Name, Email, etc...
AND
Organisation Link 1
Organisation Link 2, etc... from a link table
Because of the amount of data I want to render of the page, I figured using different controllers to render each part would make sense.. but then when saving the data do I have to use just one controller method or can I call one controller to another... I only have one form and one 'save' button for the whole page
I hope this is clearer?
You don't need to have a specific controller for each controller, although I suspect you meant to say "I have created a method accepting POST in the RenderPartial's action ..."?
When you accept the default html helper commands, it can sometimes get confusing which action will be called. For a particular web page, the tag will determine where to POST values. So the action called will be dependent on the controller/action you specify in your Html.BeginForm call.
For example, here's a form we use from an ascx page:
<% using (Html.BeginForm("InvoiceDetail" //Action
, "CompanyInvoice" //Controller
, FormMethod.Post
, new { #id = "InvoiceForm", #autocomplete = "off" }))
{%>
A form can post to any action, in any controller. Not that you'd want to, but it's quite flexible. You can also have multiple forms in a single web page now, which is great for complex forms.

POST method called on MVC UserControls as well as their parent views

Rewritten: My original post seemed to be misunderstood. I have since reported it as a bug with the following description. My original post for this question can be found below the second <HR>.
I have a major issue with POST in a user control.
I have a UserControl which has a controller containing two ActionMethods called 'ContactForm'. The second has ActionVerb.POST on it to respond to the post-back. The user control is primarily used via AJAX - but that actually is irrelevant here. Obviously these action methods render a partial view.
I have a main page containing an additional html form for 'EnterContest'. Again - its controller has two ActionMethods called 'EnterContest', one of which responds to ActionVerb.POST. This view contains the 'ContactForm' in a side bar which is rendered with :
<% Html.RenderAction("ContactUsForm", "Company", new { commentsBoxHeader = "Questions" }); %>
The problem occurs when posting back the 'EnterContest' Form (the main form on the view).
The POST request from Fiddler contains just this query string (obviously not containing any of the POST data from the contact us form because thats a completely separate HTTP ACTION).
contestId=ND09&email=fred&btnEnterContest=Submit
(yes, this looks like a GET but thats
what Fiddler shows for a POST too)
First - (as expected) - the 'EnterContest(FormCollection data) method is called in the main controller. This processes the form submission to enter the contest - calls the webservice etc..
Second - (NOT expected) - The POST method of the 'ContactForm' controller is called. This immediately crashes because it is missing expected parameters - and we don't want it called anyway. This happens during the same Http request.
If I take a look at the stack trace - it is being called from the dynamically generated aspx page - originating at the Html.RenderAction line of code shown above. So obviously what is happening is the code that is looking to partially render the 'ContactUs' action method looks at the Request and sees there is a method to handle POST so it routes it there - which is VERY BAD. Its probably somewhere around this method in the framework :
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod
This behavior is VERY confusing and really breaks what seemed to be a simple page. I'm pretty sure it is a bug - because I cannot see an elegant work around without some really clumsy checking in my controller. I think RenderAction is in futures - but I don't know if the issue is present there or in the main framework.
Just to clarify what is NOT happening :
any clever jQuery
more than one HTTP request (verified in Fiddler)
nested forms
Thanks
Original post
I am using the RenderAction Html extension in ASP.NET MVC.
I came across something unexpected, but which is making more sense as I think about it.
Lets say I have a view containing a 'RenderAction' method to generate the contact for a part of the page.
<% Html.RenderAction("ContactUsForm", "Company",
new { commentsBoxHeader = "Questions" }); %>
In this case the partial view it generates creates an ajax form which posts back via <%= Html.BeginAjaxForm() %>.
So of course I need an actionresult to handle the AJAX postback.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ContactUsForm(FormCollection formdata)
Now the problem occurs when the parent view containing this partial render action has a normal (non-ajax) form with a POST action. What happens is that the POST method for the ContactUsForm action is call in addition to the POST action for the main view. Inside this action the formdata property contains all the properties for the parent view - so ContactUsForm dies with a null reference or something like that.
I've come up with 3 possible solutions :
1) create a different action name for the post back for any user controls on the page. This has the disadvantage that you have to post back to a different function than created the partial view. Often this can be more cumbersome but this is what i'm doing right now.
2) check in every POST method (you'd have to remember to run this check in every user control's POST action method) to see if the form data is intended for that form it, and if not return a default view.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResultContactUsForm(FormCollection formData)
{
if (formData["btnSubmitContactUsForm"] == null) {
// "This form is not for us!";
// figure out how (if is possible) to return the get default view here
// and call it with the right arguments
}
}
3) report it as a bug.
What should I be doing here? I'm leaning towards thinking of this as a bug
Edit: One very important thing I need to stress more is that BOTH POST methods are called - so its not just somethig like a nested form.
Edit 2: In Fiddler I see only one request. The problem is when it tries to render the ContactUsForm after having already handled the POST for my main page it hits the 'POST' method for 'ContactUsForm' instead of the non-post handler.
EDIT2: I just noticed that you are using RenderAction instead of RenderPartial. I suspect what is happening is that it is using the RequestContext of the posted form to choose which ContactUsForm method to choose when the RenderAction is invoked. This is arguably correct behavior since the action is being invoked from a postback, just not the one you intended. I would approach this in a completely different manner. Have the partial generated by a ViewUserControl and include it on the page using RenderPartial instead. Remove the GET ContactUsForm method and only have the POST version. That is, the form itself is generated as a ViewUserControl with markup predetermined or dynamically generated via parameters passed via ViewData. The form response is handled via the controller action.
EDIT: Since you indicate that nesting is not the issue, is it possible that you are using javascript (say jQuery) to trigger the submit and your selector is too broad. If, for example, you had code like the following, that would account for the behavior you are seeing.
$(document).ready( function() {
$('#mybutton').click( function() {
$('form').submit();
});
});
Original answer: (left for context)
It sounds like you have nested forms in your view. Try moving the RenderAction outside the form in the parent view and see if that fixes your problem. My feeling about forms in MVC views is that they should be compact and only cover the markup that contains the actual inputs. This is a change from WebForms where you typically wrap all of your mark up within the form. Use CSS to control layout if you need to have the form elements appear to be intermixed.
This is actually a confirmed bug both in ASP.NET MVC 1.0 with MVC Features library and in ASP.NET MVC 2.0.
RenderAction behaves incorrectly when the request is POST.
I have submitted the bug in ASP.NET Issue Tracker on Codeplex, please vote for it :)
http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=5847

Resources