While doing a sample using MVC3 razor, I wrote:
<p>
Show me the time in:
#Ajax.ActionLink("UTC", "GetTime", new { zone = "utc" }, new AjaxOptions { UpdateTargetId = "myResults" })
#Ajax.ActionLink("BST", "GetTime", new { zone = "bst" }, new AjaxOptions { UpdateTargetId = "myResults" })
#Ajax.ActionLink("MDT", "GetTime", new { zone = "mdt" }, new AjaxOptions { UpdateTargetId = "myResults" })
</p>
<div id="myResults" style="border: 2px dotted red; padding: .5em;">
Results will appear here
</div>
<p>
This page was generated at #DateTime.UtcNow.ToString("h:MM:ss tt") (UTC)
</p>
None of my ajax calls worked until I changed this key in web.config:
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
I read in this article: http://weblogs.asp.net/owscott/archive/2010/11/17/mvc-3-ajax-redirecting-instead-of-updating-div.aspx
But now my client-side validation is not working as before.
My question is: how do I make both the ajax and client-side validations work at the same time? What does the "UnobtrusiveJavaScriptEnabled" do? Is it a switch between them?! I hope to understand more about it in simple terms.
In ASP.NET MVC 3 there are 2 things: client side validation and unobtrusive javascript which are controlled by their corresponding values in web.config:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Client side validation is based on the jquery.validate.js plugin alongside with the jquery.validate.unobtrusive.js script from Microsoft. When you include those two scripts inside a view which contains a HTML form client side validation will be performed based on the data annotation rules you have defined on your model. When you look at the generated HTML source code of the view you will notice that input fields have HTML5 data-* attributes which contain the validation rules. The Microsoft unobtrusive validation script would then read those rules and configure the jquery validate plugin.
The unobtrusive javascript is different. It is based on jquery. When you use one of the Ajax.* HTML helpers such as Ajax.ActionLink, in ASP.NET MVC 3, those helpers also emit HTML5 data-* attributes on the corresponding anchor. Those attributes are then interpreted by the Microsoft jquery.unobtrusive-ajax.js script which you need to include in your page and AJAXify those links. So for example when you write:
#Ajax.ActionLink("UTC", "GetTime", new { zone = "utc" }, new AjaxOptions { UpdateTargetId = "myResults" })
this would generate the following HTML:
<a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#myResults" href="/Home/GetTime?zone=utc">UTC</a>
As you can see now all the information about how to perform the AJAX request is contained in the DOM. So you could have a separate javascript file where you would subscribe for the click event of this link, send an AJAX request to the url contained in the href attribute and then based on the value of the data-ajax-mode attribute replace the html of some container with id contained in the data-ajax-update attribute selector. And that's exactly what the jquery.unobtrusive-ajax.js does. It's just that it is in a separate file and your markup and javascript are independent which wasn't the case in previous versions.
So contrary to ASP.NET MVC 1 and 2, in ASP.NET MVC 3 jQuery is the default javascript framework and HTML helpers are based on it. All MicrosoftAjax* scripts are no longer used.
I resolved that using this code:
#using (Ajax.BeginForm("Index2","Home",
new AjaxOptions
{
UpdateTargetId = "result",
HttpMethod = "POST"
},
new
{
onclick = "Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));",
onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, httpMethod: 'POST', updateTargetId: 'result' });"
}))
{
<input type="hidden" name="id" value='1'/>
<input type="submit" value="OK" />
}
Adding the lines:
new
{
onclick = "Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));",
onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, httpMethod: 'POST', updateTargetId: 'result' });"
}))
You're adding the same behavior than the Ajax.BeginForm without loses the javascript behavior.
I tested that, with MVC4
Related
This is the story:
I am making a commenting system, and when a user wants to add a comment they need to put data in a text area. I want to take that value typed by the user and make an #Ajax link which is to send that as a parameter to a controller.
I am using ASP.NET MVC5, and in my View() I have the following:
<textarea class="textArea" rows="3"></textarea>
<br />
#Ajax.ActionLink("Send",
"AddComment",
new { parametar = 0 , Contents = GetText() },
new AjaxOptions
{
UpdateTargetId = "beforeThis",
InsertionMode = InsertionMode.InsertBefore,
HttpMethod = "GET"
},
new { #class = "postavi btn btn-primary" })
I tried inserting under this the following:
<script type="text/javascript">
function GetText() {
return "hello there!";
}
</script>
I have in error saying that:
the name GetText does not exists in the current Context
(this is in the parameters of the #Ajax.ActionLink)
It seems I cannot integrate javascript (which could fetch me this value and razor code) How do I work this out???
PS> I have searched around for this, and either the answers for much earlier versions of MVC or the answers did not worked when I tried the same.
Make sure that you import this namespace:
using System.Web.Mvc.Ajax
You might add an event handler to the ajax link to update a custom route value.
#Ajax.ActionLink("Click", "Send", new {id = "xxx"}, new AjaxOptions(){}, new { onclick = "addParameter(this)" })
function addParameter(e) {
e.href = e.href.replace("xxx", "HelloWord");
}
What you are doing now is that you want the razor to call your JavaScript code and this is impossible. This is because Views will be rendered to HTML by Razor before they are sent to the client and Razor doesn't know about the JavaScript code, it only knows C#. All JavaScript code runs on the browser.
I suggest you use the POST method to send your comments.
You can use this code to send them:
#using (Ajax.BeginForm("AddComment", new { parametar = 0 }, new AjaxOptions()
{
UpdateTargetId = "beforeThis",
InsertionMode = InsertionMode.InsertBefore,
HttpMethod = "POST",
Url = Url.Action("AddComment")
}))
{
#Html.TextArea("Contents")
<input type="submit" value="Send" class="postavi btn btn-primary" />
}
In ASP.Net MVC 3.0 i am using a Ajax.Beginform
and hitting a JsonResult
on success of the form i am calling a jQuery Function.
but for some reason my form is redirecting to JsonAction
my View
#using (Ajax.BeginForm("ActionName", "Controller", null, new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "ShowResult"
}, new { id = "myform" }))
{
// All form Fields
<input type="submit" value="Continue" class="button standard" />
}
My controller
public JsonResult ActionName(FormCollection collection)
{
return Json(new { _status },JsonRequestBehavior.AllowGet);
}
jQuery
<script type="text/javascript">
function ShowResult(data) {
// alert("I am at ShowResult");
if (data.isRedirect) {
window.location.href = json.redirectUrl;
}
}
for some reason, when i click submit.
it runs the JSonResult and redirects the page to host/controller/actionname
I have included my
<script src="#Url.Content("jquery.unobtrusive-ajax.min.js")"></script>
in my layout.cshtml
can any one tell me what could be wrong?
I found the problem. Now i have to find the solution
on submit
I am validating my form
$("#myform").validate({
submitHandler: function (form) {
// my logic goes here....
}});
If i exclude the validation Ajax form works as expected.
But if i validate my form then ajax form is not working as expected
Thanks
when this happens its almost always because your script files aren't loaded
note from:
http://completedevelopment.blogspot.com/2011/02/unobstrusive-javascript-in-mvc-3-helps.html
Set the mentioned flag in the web.config:
Include a reference to the jQuery library ~/Scripts/jquery-1.4.4.js
Include a reference to the library that hooks this magic at ~/Scripts/jquery.unobtrusive-ajax.js
So load up fiddler http://fiddler2.com and see if the scripts are being called and loaded.
I would like to show an AJAX loading icon during an ActionResult request that can take a few seconds to process.
What is the best approach to accomplished this?
I only want to display the icon after the built it validation passes (I am using MVC3, EF Code First, so the validation is automatically put on the page).
There may be further validation/exceptions during the ActionResult, in which case a message is displayed to the user, and I'd then want the loading icon to disappear again.
Define your link as an Ajax action link and specify the ID of a spinning GIF somewhere on your page.
<div id="result"></div>
<img id="spinner" src="../content/ajaxspinner.gif" style="display: none;">
#Ajax.ActionLink("Link Text", "ActionName", "ControllerName", null, new AjaxOptions{UpdateTargetId = "result", LoadingElementId = "spinner"}, null)
or if it is a form:
#using(Ajax.BeginForm("Action", "Controller", null, new AjaxOptions{UpdateTargetId = "result", LoadingElementId = "spinner"}, null))
{
#Html.TextBox("Data")<br/>
<input type="submit" value="Submit" />
}
Put the image in a div tag like this:
<div id="busydiv" style="display:none;"><img src="busything.gif" /></div>
and then create your link like this:
#Ajax.ActionLink("Link Text", "ActionName", "ControllerName", null, new AjaxOptions { LoadingElementDuration = 1000, LoadingElementId = "busyDiv", HttpMethod = "Post", UpdateTargetId = "targetDiv", OnFailure = "PostFailure", OnSuccess = "PostSuccess", OnComplete = "PostOnComplete" }, null)
or in a form do this:
#using (Ajax.BeginForm("TestAjax", new AjaxOptions { LoadingElementDuration=1000, LoadingElementId="dave", HttpMethod = "Post", UpdateTargetId = "targetDiv", OnFailure = "PostFailure", OnSuccess = "PostSuccess", OnComplete = "PostOnComplete" }))
Obviously omitting those AjaxOptions that you don't need, as per the documentation here: http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxoptions.aspx
Just my two cents:
The solution posted by Chris is valid and will work BUT you must add a reference to the two javascript libraries below. Please note that the order matters:
<script src="~/scripts/jquery-1.8.0.js"></script>
<script src="~/scripts/jquery.unobtrusive-ajax.js"></script>
When you create an MVC application pre-loaded with bundling and all these nu-get packages this will probably not be a problem for you but if you were like me and created an empty ASP.NET MVC application you might run into issues.
I have an ajax form on razor view engine. For validation i use dataanotation classes. Validation work fine when user submit the form, validation messages work fine.
The problem is, validation wont work on keyup or blur events.
How can i activate validation without submit on ajaxform(ajax.beginform)
Here is my view code:
#using (Ajax.BeginForm(new AjaxOptions { InsertionMode = InsertionMode.Replace,
UpdateTargetId = "employeeDetail", HttpMethod = "Post", OnComplete = "Complete",
Confirm = "Confirm?" }))
{
#Html.TextBoxFor(model => model.Email)
#Html.ValidationMessageFor(model=>model.Email)
<span style="float:right"><input type="submit" class="tableGenelButton" id="submitButton" value="Kaydet" /></span>
}
Model:
[RequiredWithMessage]
[Display(Name = "E-Mail")]
public string Email { get; set; }
Update:
Ok, apparently you're using Ajax.BeginForm which uses MicrosoftAjax in stead of jQuery (I didn't realize that before). This one needs some extra work to enable client side validation:
You need
<% Html.EnableClientValidation(); %>
Somewhere in your page, and also links to MicrosoftAjax.js, MicrosoftMvcAjax.js and MicrosoftMvcValidation.js
Here's a link that might be interesting for you:
ASP.NET MVC Client Side Validation With Ajax.BeginForm
To enable client side validation for a custom validation attribute (I guess [RequiredWithMessage] is one of those), you have to implement the IClientValidatable interface.
Here is an article that explains how to do that:
The Complete Guide To Validation In ASP.NET MVC 3 - Part 2
Assuming you have client side validation enabled, you will need to call .validate() in the relevant events:
$("#theFormToValidate input").blur(function(){
$("#theFormToValidate").validate();
});
and
$("#theFormToValidate input").keyup(function(){
$("#theFormToValidate").validate();
});
I am trying to add Ajax functionality to my MVC application. I want a form to post back asynchronously. Here's the form code:
using (Ajax.BeginForm("SetInterviewee", "Date", routeValues, new AjaxOptions { UpdateTargetId = "divInterviewee" }))
and I want it to automatically post back when a dropdown list selected value changes:
<%= Html.DropDownList("interviewees", Model.interviewees.intervieweeLists.intervieweesList, "-- select employee --", new { #class = "ddltext", style = "width: 200px", onchange = "this.form.submit();" })%>
However, when I try this out, the program posts back normally, not a partial postback as I was expecting. Here's what I think the problem is: onchange = "this.form.submit();" in the dropdown list.
I think that this somehow causes a normal postback instead of the asynchronous postback.
Here's what MVC generates for HTML for the form tag:
<form action="/SetInterviewee/2011-1-26/2011-1/visit" method="post" onclick="Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));" onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, updateTargetId: 'divInterviewee' });">
I think that with "this.form.submit()" the "onsubmit" event handler is not being called. The thing is, I don't understand why. Wouldn't "onsubmit" catch any event that submits the form?
UPDATE: I went to jquery, thusly:
$(function () {
$('#interviewees').change(function () {
var form = $('#intervieweeForm');
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function (result) {
$('#selectedInterviewee').val(result);
}
});
});
});
This is causing many problems, among them:
-- It still does not seem to do an asyncrhonous postback. In my controller action method, I have the following code: "if (Request.IsAjaxRequest())" which returns false.
-- I can't seem to do model binding any more. My route looks like :
http://localhost:1986/Interviews/2011-2-25/2011-2/visit
but the route that apparently ends up being sent is
http://localhost:1986/SetInterviewee/2011-2-25/2011-2?
Count=5&Keys=System.Collections.Generic.Dictionary`2+KeyCollection
[System.String,System.Object]
&Values=System.Collections.Generic.Dictionary`2+ValueCollection
[System.String,System.Object]
causing the model binding not to work -- "visit" is supposed to be a "mode" parameter, but it's not there so "mode" defaults to "phone", which upsets the whole applecart.
It is the serialize command that is causing this? I don't understand why it would append it to the querystring when the method is POST.
There are other things -- among them, the fact that my action must return a ViewResult, so how can I possibly just return a string, which is all I need using ajax ... but I will defer that concern until I get the routing/binding thing straightened out!
UPDATE: "SetInterviewee" is indeed the correct route to post to, but the routeValues parameter should copy the route values from the current view -- I would think. Here's the code for the form:
RouteValueDictionary routeValues = ViewContext.RouteData.Values;
using (Html.BeginForm("SetInterviewee", "Date", routeValues, FormMethod.Post, new { id = "intervieweeForm" }))
So I know this is quite an old question, but I've been messing around with a similar issue and seem to come to a workaround that might prove useful in the future.
Inside your form, add a submit button. Something like:
<input type="submit" name="submit" value="save" style="display: none;" />
Make sure that you have specified the name attribute as it seems to matter in this case. Here is the code I have an it is currently working with full model binding:
<% using (Ajax.BeginForm("SaveStatus", "Finding", new { FindingId = Model.FindingId },
new AjaxOptions {
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "StatusWindow",
OnBegin = "function(){ jQuery('#SaveStatusForm').block({ Message: 'Saving' }); }",
OnComplete = "function(){ jQuery('#SaveStatusForm').unblock(); }",
OnFailure = "HandleMSAjaxFail",
}, new { id = "SaveStatusForm" })) { %>
<div>
<%: Html.DropDownListFor(Status => Status.SelectedTagId, Model.AvailableStatuses, null, new Dictionary<string, object> { { "onchange", "jQuery('#SaveStatusForm').submit();" } })%>
<input type="submit" name="submit" value="save" style="display: none;" />
</div>
<% } %>
Granted this is my code and not tied to your example, but you can get the idea from what is going on. Originally I had the dropdownlist just doing a submit and when it fired I was getting all sorts of quirky responses - including a full synchronous postback. When I added the submit button, the MS ajax code seems to work beautifully. Give it a shot!
I would recommend you to use jquery and get rid of all Ajax.* helpers and MSAjax scripts.
So:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<% using (Html.BeginForm("SetInterviewee", "Date", routeValues, FormMethod.Post, new { id = "myform" })) { %>
...
<% } %>
<%= Html.DropDownList(
"interviewees",
Model.interviewees.intervieweeLists.intervieweesList,
"-- select employee --",
new { id = "interviewees", #class = "ddltext", style = "width: 200px" }
)%>
and then in a separate javascript file:
$(function() {
$('#interviewees').change(function() {
var form = $('#myform');
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function(result) {
$('#divInterviewee').html(result);
}
});
});
});
Now we have successfully separated HTML markup from javascript. It is unobtrusive javascript.