I want to know how to use Ajax in MVC2. I created an empty project in Visual Studio and added a home controller under Controllers/Home/HomeController.cs with the following code
How do I use AJAX to call the AjaxTest method on the HomeController when the button is clicked and display that text instead?
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult AjaxTest()
{
return Json("Whoever answers this rocks!");
}
}
I added a view under Views/Home/Index.cs with the following code
<script type="text/javascript">
function sayHello() {
alert("hello stackoverflow :)")
}
</script>
<div>
Hello
<button onclick="sayHello();"> Click Me! </button>
</div>
This should work:
<script type="text/javascript">
function sayHello() {
$.get('/Home/AjaxTest', function(data) { alert(data) });
}
</script>
Remember to include jQuery in head section of your page:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
You can also include jQuery in scripts folder of your project. jQuery is a part of ASP.NET MVC framework files.
EDIT:
Change your action to
public ActionResult AjaxTest()
{
return Json("Whoever answers this rocks!", JsonRequestBehavior.AllowGet);
}
By default, using Json with get results in "This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet." error.
Don't forget that the <button> element submits the form by default, which may cause unintended effects on your AJAX calls. Consider <input type="button" value="Click Me" /> or returning false in your sayHello() function.
Related
I'm having a trouble while devolping my .net application.
I'm using the event OnTextChanged on a textbox to change the content in another Textbox, the first textbox has AutoPostBack="true", but when i write in it and click in another part, the page refreshes completely.
here is my ascx code:
<form id="Form1" runat="server">
Change text
<asp:TextBox id="txt1" runat="server" ontextchanged="ejemplo" autopostback="true"/>
<p><asp:Label id="lbl1" runat="server" /></p>
</form>
and the script in the same ascx page:
<script runat="server">
protected void ejemplo(object sender, EventArgs e)
{
lbl1.Text = "Changed";
}
</script>
I'm using MVC4,
Thanks for your answers.
EDIT:
here is a video of what is really happening:
http://remainedesign.com/video/asd.html
Life cycle of MVC and webforms both are different.
MVC is not about server controls.... viewstate... no page life cycle events in web form...
What is the 'page lifecycle' of an ASP.NET MVC page, compared to ASP.NET WebForms?
hope this helps..
Now coming to your point.
if you want to display something in the Textbox2 while entering a Value into the Textbox1 you have to use client side script, see example below
javascript
<script type="text/javascript" language="javascript">
function textCounter(field, field2, maxlimit) {
var countfield = document.getElementById(field2);
if (field.value.length > maxlimit) {
field.value = field.value.substring(0, maxlimit);
return false;
} else {
countfield.value = maxlimit - field.value.length;
}
}
</script>
Your Html page
<%using (Html.BeginForm("Index", "Account", FormMethod.Post)) // here index is a ActionName, Account is a controller name
{%>
<input type="text" id="textbox1" name="Message" onkeyup="textCounter(this,'textbox2',208)"/>
<input disabled maxlength="3" size="3" value="208" id="textbox2" /></label>
<input type="submit" value="Send" />
<%}%>
Here
textCounter() function on keyup event in textbox1 will display value in textbox2,
submit button will submit form which call action "index" on controller "Account",see below how action act
public class AccountController : Controller
{
[HttpPost]
public ActionResult index(FormCollection result)
{
string TextBoxValue=result["Message"];
return view("yourviewname");
}
}
please note,above example is solely for MVC project
i hope this example may help you..
the first textbox has AutoPostBack="true", but when i write in it and
click in another part, the page refreshes completely
That is exactly what AutoPostBack is for. If you click on another part, that's when you lose focus on the textbox and it will trigger a postback. If you need more proof then read this from MSDN:
Gets or sets a value that indicates whether an automatic postback to
the server occurs when the TextBox control loses focus.
MVC4 Internet project
I'm using Ajax.BeginForm to do a Postback with validation and it posts back the entire page rather than just the UpdateTargetID. I've looked at other posts on SO and haven't found the answer. I've built a new MVC4 Internet project just for testing (VS 2012 has been updated with 'ASP.NET and Web Tools 2012.2').
Here's my code
Controller
public ActionResult Index()
{
var vM = _db.Students.FirstOrDefault(); return View(vM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(Student vM)
{
if (ModelState.IsValid)
{ //code if Model valid
return Json(new { url = Url.Action("About", "Controller") });
}
ModelState.AddModelError(string.Empty, "AJAX Post");
return PartialView("Index", vM);
}
View
#model AJAX_Test.Models.Student
#{ ViewBag.Title = "Student"; }
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script type="text/javascript"> var onSuccess = function (result)
{
if (result.url) { window.location.href = result.url; }
}
// when server returns JSON object containing an url property redirect the browser </script>
<h1>#ViewBag.Title</h1>
<div id="IDXForm">
#using (Ajax.BeginForm("Index", new AjaxOptions() { UpdateTargetId = "IDXForm", OnSuccess = "onSuccess", HttpMethod = "Post" }))
{
#Html.AntiForgeryToken() #Html.ValidationSummary(true)
<span>#Html.EditorFor(m => m.FirstName) #Model.EnrollmentDate.ToShortDateString()</span> <input type="submit" value="Submit" />
}
</div>
The initial view is:
After Submittal:
Source code for body after submittal:
<div id="body">
<section class="content-wrapper main-content clear-fix">
<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script type="text/javascript"> var onSuccess = function (result) { if (result.url) { window.location.href = result.url; } }
// when server returns JSON object containing an url property redirect the browser </script>
<h1>Student</h1>
<div id="IDXForm">
<form action="/" data-ajax="true" data-ajax-method="Post" data-ajax-mode="replace" data-ajax-success="onSuccess" data-ajax-update="#IDXForm" id="form0" method="post"><input name="__RequestVerificationToken" type="hidden" value="vkCszJu-fKT6zUr5ys2StOTPF6a9pZdj5k1MyaAZKo8MPweS53dUuni0C9B17NjL_GVydHa7-jI1H0F9HrYEdKxeCWq9mCeER3ebaZYLxIs1" /><span><input class="text-box single-line" id="FirstName" name="FirstName" type="text" value="Carson" /> 9/1/2005</span> <input type="submit" value="Submit" />
</form></div>
Can anyone see what is wrong with my code?
Thank you.
A couple of things that come to mind that might be causing this behavior:
In your question you have shown your bundle registrations but have you actually included them in your view or Layout? Make sure that in your view or layout you have first included jquery.js and then jquery.unobtrusive-ajax.js (in that order):
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
The jquery.unobtrusive-ajax.js script is not compatible with jquery 1.9 and later because it relies on the .live() which has been removed in jQuery 1.9. So if for some reason you have upgraded your jQuery version to 1.9 or later that won't work. You should downgrade.
In your onSuccess callback you are redirecting to an url if the controller action returns a JSON. Have you verified that this is not the case? Because when a redirect happens using the window.location.href it's pretty normal that you get a full page reload and not a partial update
In all cases use a javascript debugging tool to see what exactly is happening. If you are using Firefox, then you could use FireBug. If you are using Google Chrome, you could use the Chrome Developer Toolbar. Look at the console for potential javascript errors you might have. Look at the network tab to see whether all javascripts are successfully loaded and you don't have 404 errors. Learn how to debug your javascript code with a tool. You will be surprised how much information about potential issues you might have with your code those tools will provide you.
The contents of the UpdateTargetID must be in a partial view and that partial view needs to be called from the Controller Post Action. Darin answered me through e-mail (thank you Darin). You need to use a parital view. I've tried to update his answer twice and the moderators have not done it or provided an explanation why so I'm posting my own answer for others benefit.
_MyForm View:
#model AJAX_Test.Models.Student
#using (Ajax.BeginForm("Index", new AjaxOptions { UpdateTargetId = "IDXForm", OnSuccess = "onSuccess" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<span>
#Html.EditorFor(m => m.FirstName) #Model.EnrollmentDate.ToShortDateString()
</span>
<input type="submit" value="Submit" />
}
Main View :
<div id="IDXForm">
#Html.Partial("_MyForm")
</div>
Controller Post Action:
ModelState.AddModelError(string.Empty, "AJAX Post");
return PartialView("_MyForm", vM);
use:<script src="../Scripts/jquery.unobtrusive-ajax.js"></script>
This JS is what makes Ajax work.
Couple of other things to note.
jquery.unobtrusive-ajax.js now supports JQuery 1.9. I have installed jquery.unobtrusive-ajax.js version 3.0.0 and it is working with JQuery 1.9
2. Make sure all the div tages are closed properly, including the view which contains the Ajax.BeginForm and the main view. Also if you have #Html.Raw() in the main view or inside the view which contains Ajax.BeginForm be cautious about that too.
Posting here to save one day of head scratching.
make sure you have your bundles config include this
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
At a minimum, you need these two includes:
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
And if that still does not help, check in web.config and make sure unobtrusive is enabled:
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
And if that still has no effect, make sure unobtrusive js files are compatible with current jQuery version, whatever version of jQuery you are using, which can be found at a below URL:
http://www.nuget.org/packages?q=unobtrusive
I have the same problem as posted here
I have a <button> element that triggers "A potentially dangerous request.form value..." error in asp.net MVC. For instance:
<button type="submit" name="logon" value="ok">Confirm</button>
<button type="submit" name="cancel" value="ok">Cancel</button>
And this javascript (with jquery UI 1.8.5)
<script type="text/javascript">
$(document).ready(function() {
$("button").button();
});
</script>
The issue is that I can't remove the name property (as the given solution in the link I posted) because I capture which button is pressed in the controller side this way:
public ActionResult Logon(FormCollection form, string logon, string cancel)
{
if (!string.IsNullOrEmpty(logon))
{
DoLogon();
}
if (!string.IsNullOrEmpty(cancel))
{
Cancel();
}
//etc
}
Is there any workaround for this? Thanks. Note that I don't have this problem in IE8 or firefox.
Have you seen this?
Cause
The .NET framework is throwing up an error because it detected something
in the entered text which looks like an HTML statement. The text doesn't
need to contain valid HTML, just anything with opening and closing
angled brackets ("<...>").
The solution proposed there is to disable the request validation on the server-side:
<pages validateRequest="false" />
Be sure to read through the warnings and explanations as well.
I'm new to MVC and I'm implementing the Nerd Dinner MVC sample app in MS MVC2. I'm on step 10, "Ajax enabling RSVPs accepts". I've added the new RSVP controller and added the Register action method like so:
public class RSVPController : Controller
{
DinnerRepository dinnerRepository = new DinnerRepository();
//
// AJAX: /Dinners/RSVPForEvent/1
[Authorize, AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsUserRegistered(User.Identity.Name)) {
RSVP rsvp = new RSVP();
rsvp.AttendeeName = User.Identity.Name;
dinner.RSVPs.Add(rsvp);
dinnerRepository.Save();
}
return Content("Thanks - we'll see you there!");
}
}
I added the references to both Ajax script libraries and added the code below to the Details view as described in the article:
<div id="rsvpmsg">
<% if(Request.IsAuthenticated) { %>
<% if(Model.IsUserRegistered(Context.User.Identity.Name)) { %>
<p>You are registred for this event!</p>
<% } else { %>
<%= Ajax.ActionLink( "RSVP for this event",
"Register", "RSVP",
new { id=Model.DinnerID },
new AjaxOptions { UpdateTargetId="rsvpmsg"}) %>
<% } %>
<% } else { %>
Logon to RSVP for this event.
<% } %>
</div>
When I click the "RSVP for this event" link I get a 404 eror saying the resource cannot be found:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /NerdDinner/RSVP/Register/24
Version Information: Microsoft .NET Framework Version:2.0.50727.4200; ASP.NET Version:2.0.50727.4205
When I step into the code it is finding the Register action method correctly. After playing around with it I removed the "AcceptVerbs(HttpVerbs.Post)" from the constraint on the Register method, and it then worked. However it didn't reload the page it just displayed the "Thanks - we'll see you there" message on a new blank page. Looking at the html in the details page there is no Form submit taking place, so I'm wondering does the Ajax code need something more to make the call a Post? Is there a known issue with this part of the Nerd Dinner app? I think the app was written in MVC1 and I'm using MVC2 - does this make a diference?
TIA,
Ciaran
The PDF tutorial (versus the online HTML version) has typographic ANSI quote characters (0x94) rather than ASCII (0x22) in the HTML block of script elements. The correct block is shown below with all of the quote characters replaced.
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
Visual Studio will mark the JavaScript source files with the Warning green squiggles ("File not found") but not the type attributes so you may notice and correct the problem only for the source files. However, the type attributes will still be malformed and this will cause the scripts not to be loaded correctly in the browser.
Using the Chrome developer tools, I noticed that the scripts were not listed as Resources for the Details HTML page. Correcting the quote characters for the type attributes allowed the Register action to work as documented in the tutorial with no changes.
This portion of your action explains why you just get the "see you there" message:
return Content("Thanks - we'll see you there!");
That's all that's being returned.
The reason you were getting a 404 to begin with is the use of an actionlink:
Ajax.ActionLink(...
That will create a URL link, a GET not a POST, and the AcceptVerbs(HttpVerbs.Post) would have forced no match. You should submit a form to do a post:
using (Ajax.BeginForm("Controller", "Action", new AjaxOptions { UpdateTargetId = "f1" } )) { %>
<div id="f1">
<!-- form fields here -->
<input type="submit" />
</div>
<% } %>
As an additional comment to debugging issues with this problem, being a Java/JSF developer, I ran into a hard lesson that
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript" />
and
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
are processed differently. The first not working at all and the second working correctly.
This is the Details.cshtml used in MVC3. The problem with redirecting using GET, and not POST is similar.
<div id="rsvpmsg">
#if (Request.IsAuthenticated)
{
if (Model.IsUserRegistered(Context.User.Identity.Name))
{
<p>
You are registered for this event</p>
}
else
{
#Ajax.ActionLink("RSVP for this event",
"Register",
"RSVP",
new { id = Model.DinnerID },
new AjaxOptions { UpdateTargetId = "rsvpmsg", HttpMethod = "Post" })
}
}
else
{
<p>
Logon to RSVP for this event.</p>
}
</div>
#section JavaScript
{
<script src="#Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>;
<script src="#Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>;
}
Ok, so previously i have mentioned that i had the same problem, and it comes from the fact that MVC 3 uses unobtrusive JavaScript.
To make this work, you have 2 solutions, one is to disable Unobtrusive Javascript in your webconfig file:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Just set it to false, and during page build, javascript generated for the Action link will be normal inline javascript, that works fine, and results with something like this in HTML:
<a onclick="Sys.Mvc.AsyncHyperlink.handleClick(this, new Sys.UI.DomEvent(event),
{ insertionMode: Sys.Mvc.InsertionMode.replace, httpMethod: 'Post', updateTargetId: 'rsvpmsg' });" href="/RSVP/Register/13">RSVP for this event</a>
Second solution is more to my liking and it is just as simple. You just have to include additional javascript source file in your header:
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
#RenderSection("JavaScript",required:false)
</head>
The resulting javascript generated is unobtrusive, and results with this in HTML:
RSVP for this event
In both cases the resulting functionality is the same, and the second solution is "more in spirit" of new MVC 3.
Just in case it helps someone else, i had the problem using MVC 3 and it was because I had linked to the MS AJAX libraries and MVC 3 actually uses jQuery by default so I just needed to uncomment the links in my master page and it was fine.
To make an http post with Ajax.ActionLink , you'd have to do e.g. new AjaxOptions { UpdateTargetId="rsvpmsg",HttpMethod="POST"}
if you include those two in your site.master, it should be fine
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
I was trying to convert to MVC3/Razor as I worked through this example. I've been stuck on this exact same issue for at least 24 hours now...exact same symptoms. I tried everything on this page that I could understand or thought was relevant.
I didn't have the unobtrusive javascript mention in my web.config and was considering adding it with the "false" value thinking "true" might be the default. However, I was thinking it might screw something else up (among who knows what else).
I found the following tid-bit over on the wrox forum. If I add the following line of code to the second line of my RSVPStatus.cshtml partial view:
<script src="/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
Everything works as intended. I know Zak mentioned that line of code above (and a bunch of other stuff that lead me in the right direction), but I was using the partial view and haven't seen a head tag since I started messing with MVC. I know it's probably there somewhere, but all the smoke and mirrors of what is MS programming now, makes it harder to dissect and I probably would have gone down Zak's path at some point. So, +1 for him.
Anyway, hope this helps someone save a day.
I am tryng to use this: http://jqueryui.com/demos/dialog/#modal-form
I have:
<script type="text/javascript">
$(document).ready(function() {
$("#dialog").dialog();
$("#dialog").dialog('close');
$('.myPop').click(function() {
$("#dialog").dialog('open');
});
});
Which allows me to pop-up on the click of '.myPop' which is just a temp input button in my list which is working:
<button type="button" class="myPop"></button>
My question is - what is the best way to use this pop-up to go to the Edit method of my controller, populate controls and then be able to save back to the model and refresh the list page?
I want to keep with best practice in ASP.Net MVC please.
Am I beetr maybe using this? http://dev.iceburg.net/jquery/jqModal/
Thanks
There's obviously a bunch of ways to do that, but here's how I would solve it. Perform an ajax call before loading the dialog to populate the dialog's contents, show the dialog, than on save close the dialog and refresh the grid. Those are the basics, there's some helper code below. I find it a good practice to return a json result from the save action to determine if the saved was successful, and if not an error message that indicates why it failed to display to the user.
<div id="dialog" title="Basic dialog">
<!-- loaded from ajax call -->
<form id="exampleForm">
<input blah>
<input type="button" onclick="Save()" />
</form>
</div>
<script>
$(function() {
$('.myPop').click(function() {
$.get("editController/loadContents", function(data){
$("#dialog").html(data);
});
$("#dialog").dialog('open');
});
});
function Save(){
$.post("/editController/Edit", $("#exampleForm").serialize(),
function(data){
$("#dialog").dialog('close');
//update grid with ajax call
});
}
</script>