ASP.NET MVC Preview 4 - Using Ajax and Ajax.Form
ASP.NET MVC Preview 4 is up on CodePlex. The Gu has all the exquisite Gu-Like Detail on his blog. Phil Haack has some notes on this release on his blog.
If you take a look at the generated "changes" document, it shows a bunch of new stuff like AjaxHelpers and AjaxExtensions that set the stage for some interesting things the community could do with ASP.NET MVC and Ajax. I'd like to see some JQuery love in there, maybe with some MVCContrib as they've been quiet lately.
Using the new Preview 4 bits, here's what I was able to get running in just a few minutes.
Given a ViewPage that has a TextBox and a Button on it, when I click the button (and submit the form) I'll call back to the server and get some text that should then go in the div next to the button.
The View looks like:
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<p>
<%using (Ajax.Form("ExamineTextBox", new AjaxOptions { UpdateTargetId = "result" }))
{ %>
<%= Html.TextBox("textBox1")%>
<input type="submit" value="Button"/>
<span id="result"/>
<% } %>
</p>
</asp:Content>
Notice the Ajax.Form helper and the UpdateTargetID that refers to the span. There's more AjaxOptions in there to explore as well, that we'll see in a second. The controller action looks like this:
public class HomeController : Controller
{
public string ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return "This text is MVC different from before!";
}
return String.Empty;
}
}
Notice that the return method of the ExamineTextBox isn't an ActionResult, it's a string. In fact, the string result is being wrapped for you into a ContentResult. You could certainly make a ContentResult yourself, but this makes for a nicer looking method signature.
The result of that method is returned via the AJAX call, then put into that span via magic and pixie dust. Actually, the request looks like this:
POST /Home/ExamineTextBox HTTP/1.1
Referer: http://localhost.:45210/Home
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Accept-Encoding: gzip, deflate
Host: localhost.:45210
Content-Length: 28
Connection: Keep-Alive
Pragma: no-cache
textBox1=dude&__MVCAJAX=true
and the Response like this:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 39
Connection: Close
This text is MVC different from before!
And that UpdateTargetID (the span) mentioned in the Ajax Form helper above? That's swapped in via the magic in MicrosoftMvcAjax.debug.js. There are options for before, after and replace.
// Insert the results into the target element
if (targetElement) {
switch (insertionMode) {
case Sys.Mvc.InsertionMode.Replace:
targetElement.innerHTML = executor.get_responseData();
break;
case Sys.Mvc.InsertionMode.InsertBefore:
targetElement.innerHTML = executor.get_responseData() + targetElement.innerHTML;
break;
case Sys.Mvc.InsertionMode.InsertAfter:
targetElement.innerHTML = targetElement.innerHTML + executor.get_responseData();
break;
}
}
Note that I had to manually (for now) add the JavaScript libraries, so I put them in my Site.Master View.
<script src="/Content/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="/Content/MicrosoftMvcAjax.debug.js" type="text/javascript"></script>
Also, notice that the MicrosoftMvcAjax.js is new and it's in your /Content folder if you make a new MVC Application. Congrats to Phil and Eilon and the team for this release!
Related Links
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
anyway, i didn't mean to be negative. all this stuff is great. i hope there will be an article on using IronRuby with ASP.NET MVC Preview 4. there was supposed to be some support from it if I remember correctly.
-Seth
Thanks for the post.Different choices are good things and I am happy that MVC is pluggable to any client side javascript frameworks. If anyone like jQuery or other frameowork, they can use that one and anyone like MS Ajax they can use it. Don't argue for a single framework. The MVC team should learn lesson from the problems of ASP.net Ajax while developing Ajax helpers for MVC. The fact is that JQuery is very popular among the web develoeprs regardsless of specific community.Please provide samples in both JQuery and MS Ajax.
Thanks,
Shiju Varghese
I'll stick to my custom self-written ajax library for now, hoping to see something in the future. The MVC framework is awesome, been waitin for it for ages, and all you guys are doing wonders, keep it up!
Anyway, forgot to include a link to my p3 version of jQuery love
I'm missing HtmlHelpers such as SubmitButton, Image - were they removed?
@Jamie We wanted to provide a small set of simple Ajax helper methods for those who aren't as familiar with Javascript libraries. These can enable simple scenarios, and we don't plan on having a huge number of them. For that, I think they still provide value and for those who are competent with good JS libraries, you can totally ignore them. We'll also be digging into various ways of swapping in JQuery. Watch my blog for some posts on that.
the button builder always builds a closed tag button, which is invalid and causes serious rendering bugs in the HTML. the button tag has to be open:
<button arg="val">Text</button>
How about something less abusive, like:
<%= Ajax.Form(...) %>
<%= Ajax.EndForm() %>
How about changing it to something where you're at least doing some sort of server side validation on the textbox input instead of something that could have been done without the postback to the server.
I'm just saying it's a really confusing example... and it's hard to see what you're exactly getting with Ajax.Form.
1. <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
2. <p>
3. <% using (Ajax.Form("UsernameExists", new AjaxOptions { UpdateTargetId = "result" }))
4. { %>
5. <%= Html.TextBox("username")%>
6. <input type="submit" value="Button"/>
7. <span id="result"/>
8. <% } %>
9. </p>
10. </asp:Content>
public class HomeController : Controller
{
public string UsernameExists(string username)
{
string[] existingUsers = { "ScottGu", "ScottHa", "GuyIncognito", "Boris" };
if (existingUsers.Contains(username))
{
return "The username is already in use";
}
else
{
return "The username is available";
}
}
}
@me.yahoo.blahblahblahb
I haven't run this example yet, but if it's truly an "ajax" example, the entire page should NOT post back to the server and reload entirely (which would cause you to lose whatever value was in the the textbox). The postback should happen behind the scenes without the page reloading. I'll have to try out the new MVC 4 bits and see what you mean, cause I'm confused...
And also I'll much more like to use ASP MVC Ajax rather than jQuery. It is a matter of personal preferences after all. I for one have never used ASP.NET before mostly because I didn't find it appealing enough. Ever since MVC was introduced things changed and I hope it will be ready for release soon =p~.
Congrats to the MVC Team you are building a great piece of software.
I'd vote for jQuery support too. :)
I worked at a Flex shop previously and am familiar with the Cairngorm MVC. You can consider me 'relatively' new in the .NET arena. I have a few more questions -
1) Where are you keeping the state - server? Saw the runat="server" controls on your examples. What happens when one page depends on the input values from other pages? I am used to keeping it in the Model as Value Objects.
2) How does the 'session' come into play in this?
You guys are doing great work with MVC and the Ajax helpers. One question though: why are the helpers sealed? That could be a great extensibility point for other JS frameworks.
Here is the jQuery love you asked for:
http://blog.goeran.no/PermaLink,guid,e55bfb55-ac10-48db-98a4-d28343e0f98a.aspx
Here is the jQuery love you asked for:
http://blog.goeran.no/PermaLink,guid,e55bfb55-ac10-48db-98a4-d28343e0f98a.aspx
Here's the scenario. I have a table and at the end of each row is a delete button when I press the delete button I want to delete the item and remove the row from the table using the Ajax.ActionLink I can set the target to the id of the row and remove the innerHTML but this doesn't completely remove the row causing the html rendering to show a couple of pixel gap where the row used to be. This makes the table look messy. I could surround the tr tags with span or div however this isn't exactly valid XHTML
I've tried with IE 7 and the HTML was messy after the async callback because of the way the result was rendered (the footer goes away).
I've changed the markup to fix it up: <span id="result"></span>
for example:
<%using (Ajax.Form("Update", new AjaxOptions { UpdateTargetId = "result" }))
{ %>
<input type="hidden" id="id" name="id" value="foo" />
<input type="submit" id="submit" name="submit" value="Add"/>
<span id="result" />
<% } %>
(note: the above code was never run, so there may be an error or two)
in the action, I cannot view the value of my submit button. I tested with the hidden input, and that worked great, but on a form that has several buttons, you need to be able to pull out the value, or have a different way of distinguishing which of the buttons was pressed.
You'd have to put the text right back into the Textbox, I'm afraid!
Hey Scott, any way to avoid this and have this app behave like an Ajax app should? I need the form data to remain in the form after the asynch form submission.
Using <script type="text/javascriptscript" src="../../Content/MicrosoftAjax.debug.js"></script> certainly doesn't work! Unlike <link/> tag for CSS, where it automatically resolves it relative to current page, it doesn't do this for scripts. And I can't seem to find any other way to get it to register using code behind.
Someone save me from my stupidity trying to get this to work! :P
Comments are closed.