Ajax.BeginForm helper not loading partial view into specified DIV - asp.net-mvc

I am working with MVC trying to load the results of a form submission into a specific DIV.
Below is the code of my form:
<div class="segmentForm clearfix">
<% using (Ajax.BeginForm("ShopByAirCriteria", "AirOption", new AjaxOptions { UpdateTargetId = "DynamicAirOptions", InsertionMode = InsertionMode.Replace, HttpMethod = "POST", OnBegin = "return loadingBar();" }, new { #name = "AirOptionSegment_Air" }))
{ %>
<%
Html.RenderPartial("AirOneWay", Model);
%>
<br/>
<div class="agent-actions">
Load Original Data
<input type="submit" class="btn green" id="a1" name="SearchAir" value="Search" />
</div>
<% } %>
</div>
I have included the necessary js files in my site master:
<script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")%>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")%>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.js") %>"></script>
But somehow, the Partial view that is rendered by the AirOption/ShopByAirCriteria action method is not being loaded in the DynamicAirOptions div but in a new page.
Any idea on what the issue might be?
It was working properly when I was using the html.BeginForm helper, but I changed it to use the ajax helper instead because I need to load the results into a specific div. Is there any way to specify the TargetID with the html helper?

I would caution against using Ajax.BeginForm. It's a bit of a hold-over from Web Forms, and in my humble opinion, should never be used under any circumstances. It hides logic and therefore leads the developer pretty inevitably into a situation like yours, where it's not working and there's no obvious reason why. Explicit is always better than implicit; when you control the AJAX call, you'll always know why it does or does not work.
So, just use a regular Html.BeginForm and then tie into the submit event with some custom JavaScript. Make your AJAX call to submit the form in your event handler and then render the resulting response to the page in the div you want. Since you're already using jQuery, this is super simple:
$('#YourForm').on('submit', function (evt) {
evt.preventDefault();
$.post('/some/url', $(this).serialize(), function (response) {
$('#YourDiv').html(response); // assuming response is HTML
});
});
A side benefit to this approach is that you're not crippling the standard form. It's still just a regular old form, so if JavaScript is disabled, or not available at all (such as with many screen readers used for the blind), the form can still submit the standard old way and return a new page with the results.

Have you include jquery before jquery.unobtrusive-ajax.js? it could be also some javascript error, check Console in your browser developer tool.
I've paste your code in blank mvc4 app and works as expected.
Master:
<script src="/Scripts/jquery-1.8.2.js"></script>
<script type="text/javascript" src="/Scripts/jquery.unobtrusive-ajax.js"></script>
View:
<div class="segmentForm clearfix">
<% using (Ajax.BeginForm("ShopByAirCriteria", "AirOption", new AjaxOptions { UpdateTargetId = "DynamicAirOptions", InsertionMode = InsertionMode.Replace, HttpMethod = "POST" }, new { #name = "AirOptionSegment_Air" }))
{ %>
<div id="DynamicAirOptions">
</div>
<br/>
<input type="submit" class="btn green" id="a1" name="SearchAir" value="Search" />
<% } %>
</div>

My problem was using the following in my layout. I believe it was loading unnecessary files that were causing a conflict. It all worked fine in Edge and Safari, but the PartialView would not render inside the div on Chrome. It would display in a new page.
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
Instead of using the bundles, I went with this and Ajax.BeginForm works great!
<script src="~/Scripts/jquery-1.10.2.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>

Related

Ajax ActionLink: InsertionMode -- Partial View always replaces entire view

I am trying to get an Ajax ActionLink to insert a small amount of content into a div within a view. No matter what I try, instead of inserting the content into the div with the rest of the HTML in the view in tact, it wipes out the entire existing view, and sends only the partial to the browser.
<div> Other Stuff</div>
#Ajax.ActionLink("Click here to see the latest review",
"LatestReview", new AjaxOptions
{
UpdateTargetId = "latestReview",
InsertionMode = InsertionMode.ReplaceWith,
HttpMethod = "GET",
LoadingElementId = "progress"
})
<div id="latestReview"></div>
<div>More Stuff</div>
So we start with this HTML:
<div> Other Stuff</div>
<a data-ajax="true" data-ajax-loading="#progress" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#latestReview" href="/Home/LatestReview">Click here to see the latest review</a>
<div id="latestReview"></div>
<div>More Stuff</div>
And what I want after the link is clicked it this:
<div> Other Stuff</div>
<a data-ajax="true" data-ajax-loading="#progress" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#latestReview" href="/Home/LatestReview">Click here to see the latest review</a>
<div id="latestReview">[Content Of The Latest Review]</div>
<div>More Stuff</div>
But instead, I get this:
<html><head></head><body>
<div class="review">
content of partial view
</div>
</body></html>
I have tried all the options within InsertMode: InsertAfter, InsertBefore, Replace, and ReplaceWith. I'm probably missing something simple. Just not sure what it is.
The problem turned out to be a miss-match between jquery files. I downloaded the latest versions of jquery, jquery-ui, and jquery.unobtrusive, and then it worked.

Why are all the Razor Views in my app caching?

I have a MVC 3 application where I am using razor views. I have a SiteLayout.cshtml page, which is my master page for the site. Then, I have a Login.cshtml page which uses the SiteLayout.cshtml as the master page. I also have a _ViewStart.cshtml page that applies the master page to all cshtml pages.
I recently added a 'Forgot password' link to my login page. When I run the app, it doesn't show the new link. I cleaned the solution & rebuilt the solution, but that didn't help. Its almost like the razor views are getting cached. I checked all my browser settings (IE, Firefox, Chrome) to make sure that they are not caching.
I am totally stumped with this one. Any ideas??
Here is the code for the master page:
#using System.Web.UI.WebControls
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head runat="server">
<title>Application - #ViewBag.Title</title>
<script src="/Scripts/jquery-1.7.min.js" type="text/javascript"> </script>
<script src="/Scripts/jquery.tools.min.js" type="text/javascript"> </script>
<link rel="stylesheet" type="text/css" media="all" href="/Content/Site.css" />
</head>
<body>
<!-- Total width: 1180px -->
<div id="maincontainer">
<div id="header">
<span style="text-align:left; float:left;">Header</span>
<span style="text-align:right; float:right; width:200px;">#Html.Partial("LoginStatus")</span>
</div>
<div id="maincontent">
#RenderBody()
</div>
</div>
</body>
</Html>
Code for the login view:
#{
ViewBag.Title = "Login";
}
<div style="width:500px;">
#using(Html.BeginForm("Authenticate", "Account", FormMethod.Post))
{
<fieldset>
<legend>Login</legend>
<div class="errorMessage">#Html.ValidationMessage("LoginError")</div>
<label for="Email">Email</label>
#Html.TextBox("Email", string.Empty, new { #style = "width:250px;" })
<label for="Password">Password</label>
#Html.Password("Password", string.Empty, new { #style = "width:100px;" }) <br/><br />
<div class="buttons">
<button type="submit" class="positive" name="login">
<img src="/Content/images/lock_open.png" alt=""/>
Login
</button>
</div>
<p>#Html.ActionLink("Forgot Password?", "ForgotPassword", "Account")</p>
</fieldset>
}
</div>
Finally, code for _ViewStart:
#{
Layout = "~/Views/Shared/SiteLayout.cshtml";
}
Hit [control] + F5 to force a refresh.
Above each Action method you can set an output caching attribute for that page. Here is an article on it output caching
Alternatively you can set your caching preferences site wide in the web.config
Besides cleaning and rebuilding, which you mentioned you had done, You might want to check and make sure you don't have any instances of your .NET Development server running.
If you don't want caching to occur at all, you can use the following attribute to ensure that nothing is cached:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
//Your Controller Here
I think I have it figured out. I am sure it has something to do with the configuration of my machine since its not happening to others. So, instead of allowing VS2010 to assign its own port, I forced-picked a port. And I now get the new view.

MVC2 Ajax Form does unwanted page refresh

I am pretty new to MVC. I have my first Ajax Form here:
<div id="test"></div>
<div id="MainChatMenu">
<% using (Ajax.BeginForm("SendMessage", "MainChat", new AjaxOptions { UpdateTargetId="test"}))
{ %>
<input id="chatMessageText" type="text" maxlength="200" />
<input type="submit" value="Go"/>
<% } %>
Now, if I click the submit button, the page is reloading, goint to mysite/controller/action.
I thought that the default behaviour of the Ajax.BeginForm was exactly not to do that?
Where's my newbie mistake?
My Controller is called correctly, but data passing also doesn't work. Probably because of the same mistake?
Here's the code:
public class MainChatController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public EmptyResult SendMessage(FormCollection formValues)
{
return new EmptyResult();
}
}
Make sure you have included the necessary script libraries:
<script type="text/javascript" src="<%= Url.Content("~/scripts/MicrosoftAjax.js") %>"></script>
<script type="text/javascript" src="<%= Url.Content("~/scripts/MicrosoftMvcAjax.js") %>"></script>
<% using (Ajax.BeginForm("SendMessage", "MainChat", new{}, new AjaxOptions { UpdateTargetId="test", HttpMethod="POST"})) %>

How to dispatch on the result of submiting an AJAX form in ASP.Net MVC?

In ASP.Net MVC, having a form more or less like this:
<% using (Ajax.BeginForm(new AjaxOptions() { OnSuccess="onSuccess"})) {%>
<p>
<label for="Comment">Comment:</label>
<%= Html.TextArea("Comment")%>
<%= Html.ValidationMessage("Comment", "*")%>
</p>
<p><input type="submit" value="Submit comment" /></p>
<% } %>
How can the onSuccess Javascript function know whether the result is another version of the form because it didn't validate, a comment as a div to add to the list of comments or a log in page that should be pop up for logging in?
You can define that in your returning JSON or whatever transport method you use?
Not sure if that's what you're looking for, but also: this is how the onSuccess function is called:
YourFunction(ajaxContext);
AjaxContext is defined as follows:
AjaxContext ajaxContext = new AjaxContext(request, updateElement, loadingElement, ajaxOptions.InsertionMode);
You should replace the code inside your ajax form with a new partial view, then you will return that partial view from your controller. The partial view would consist in:
<p>
<label for="Comment">Comment:</label>
<%= Html.TextArea("Comment")%>
<%= Html.ValidationMessage("Comment", "*")%>
</p>
<p><input type="submit" value="Submit comment" /></p>
This way, your partial view works just like a regular view.
Unfortunately there is no simple way to execute javascript as a response (since you are responding with a view). It would be easier if your response was a Json string, but in that case, you can't use the AjaxForm because the Json string would be rendered on screen as a result of submitting the form (and processing its response). This may work though (I haven't tried it):
<p>
<label for="Comment">Comment:</label>
<%= Html.TextArea("Comment")%>
<%= Html.ValidationMessage("Comment", "*")%>
</p>
<p><input type="submit" value="Submit comment" /></p>
<script type="text/javascript">
function processResponse(data){
// blah blah blah
}
processResponse(<%= ViewData["dataFromTheController"] %>);
</script>
Your could simply add different CSS classes to the root elements of your responses (for example .form, .comments, .login). And then (for example in jQuery):
var response = $(responseContent);
$('.form', response).each(function() {
// $(this) is form
});
$('.comments', response).each(function() {
// $(this) is comments
});
$('.login', response).each(function() {
// $(this) is login page
});
How can the onSuccess Javascript
function know whether the result is
another version of the form because it
didn't validate, a comment as a div to
add to the list of comments or a log
in page that should be pop up for
logging in?
The short answer is that it cannot unless you explicitly validate it. That's because JSON is transported as a string and when the client side Javascript gets the string.
For starters you should implicitly know what sort of object to expect. If you are calling an web service # Cars/List then you know the returned object will be a list of cars and you parse that appropriately in your client. You can run into errors which you should handle appropriately by retrying the request or logging them or showing an error message.
I would recommend you to use the jquery.form plugin, with this you can have a normal form to act like an ajax one, like this:
<script type="text/javascript">
// wait for the DOM to be loaded
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#myForm').ajaxForm(function() {
alert("Thank you for your comment!");
});
});
</script>
<form id="myForm" action="comment.php" method="post">
Name: <input type="text" name="name" />
Comment: <textarea name="comment"></textarea>
<input type="submit" value="Submit Comment" />
</form>

Submitting AjaxForm with jQuery in ASP.NET MVC

I have an ajax form in asp.net mvc which is as simple as this:
&lt% using (this.Ajax.BeginForm("LatestBlogPosts", "Blog", null, new AjaxOptions { UpdateTargetId = "blogPostPanel" }, new { id = "BlogPostForm" })) { %>
<div class="panel" id="blogPostPanel">
<img src="/images/ajax-loader.gif" alt="ajax-loader" />
</div&gt
<% } %>
I want to invoke the form submit when document is loaded. This should supposedly, call the controller's action and return a result that should be replaced with the placeholder DIV. If I add a SUBMIT button to the form, it works perfectly, but when I invoke the submit via jQuery, the whole page is refreshed, and the content returned by the server is displayed in the newly displayed page. Here's my jQuery code:
<script type="text/javascript">
$(document).ready(function() {
$("#BlogPostForm").submit();
});
</script>
Anyway to do this?
I think it may work if you use the trigger method to generate the submit event, but I think there's a less complicated way to do this using jQuery.
<div class="panel" id="blogPostPanel">
<img src="/images/ajax-loader.gif" alt="ajax-loader" />
</div>
<script type="text/javascript">
$(function() {
$('#blogPostPanel').load( '<%= Url.Action( "LatestBlogPosts", "Blog" ) %>' );
});
</script>

Resources