it's my very first post here so please be tolerant,
I'm struggling with #Ajax.Something calls, it's almost working correctly.
I get the proper result but not in the proper view i loose the content the url also changes.
View :
<p>Ajax result :</p>
<div id="Result">
#{
Html.RenderAction("_result");
}
</div>
#Ajax.ActionLink("Update", "_result", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "Result",
HttpMethod = "GET"
})
<p>normal vue : #DateTime.Now.ToLongTimeString()</p>
<h2>#Html.Encode(ViewData["Message"]) </h2>
<p>
Page Rendered: #DateTime.Now.ToLongTimeString()
</p>
<span id="status">No Status</span>
<br />
#Ajax.ActionLink("Update Status", "GetStatus", new AjaxOptions{UpdateTargetId="status" })
<br /><br />
#using(Ajax.BeginForm("UpdateForm", new AjaxOptions{UpdateTargetId="textEntered"})) {
#Html.TextBox("textBox1","Enter text")
<input type="submit" value="Submit" /><br />
<span id="textEntered">Nothing Entered</span>
}
Partial vue _result :
<p> Ajax call worked</p>
<p>partial vue : #DateTime.Now.ToLongTimeString()</p>
Controller :
public ActionResult SimpleAjax()
{
return View();
}
public ActionResult _result()
{
return PartialView();
}
public string GetStatus()
{
return "Status OK at " + DateTime.Now.ToLongTimeString();
}
public string UpdateForm(string textBox1)
{
if (textBox1 != "Enter text")
{
return "You entered: \"" + textBox1.ToString() + "\" at " +
DateTime.Now.ToLongTimeString();
}
return String.Empty;
}
Screenshots :
main vue loaded :
Vue SimpleAjax
after clicking on "update :
_result
So in some ways i do call the right view and display it, but i actually don't render it as an update, as expected.
I'm still novice in Razor, and developpement in general, but i like to understand when it doesn't work so i can fix it. I tried the easiest way to test these ajax calls, with different approaches.. and nothing seems to work for me at the moment.
I'm pretty sure it's juste me being dumb not seeing the evidence right before me.
So if anyone has any idea about how to fix it i'm trying to make an auto completion drop down list, with of course ajax call included, and i'm stuck here not able the achieve the easiest call ever.
Please, make sure you have installed and included in bundle jQuery Unobtrusive. (nuget package here: https://www.nuget.org/packages/Microsoft.jQuery.Unobtrusive.Validation/). Also, make sure you've enabled client validation and unobtrusive javascript
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
I've replicated your app making the following modifications:
1) I've installed Microsoft.jQuery.Unobtrusive.Ajax and Microsoft.jQuery.Unobtrusive.Validation. In packages.config:
<package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.3" targetFramework="net461" />
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net461" />
2) in _Layout.cshtml (make sure to include the js resources only once. also, make sure to have jqueryval befor jquery-unobtrusive):
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jquery-unobtrusive")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
3) In Bundle.Config I've added a bundle for the unobtrusive package:
bundles.Add(new ScriptBundle("~/bundles/jquery-unobtrusive")
.Include("~/Scripts/jquery.unobtrusive-ajax.js")
.Include("~/Scripts/jquery.validate.unobtrusive.js"));
4) in _result.cshtml I've added:
#{ Layout = null; }
It works without other modifications
Related
I am trying to update my Razor view content using ajax in ASP.Net MVC 5. But, everytime its loading total page instead of partial request to the controller.
Please help which resources i need to add to my prject to work with ajax in MVC5 speciafically.
Resources Attched to my project to use Ajax:
jquery.unobtrusive-ajax.min.js
View Design:
#using (Ajax.BeginForm("RoomsAvail", "Bookings", new AjaxOptions
{
HttpMethod = "GET",
UpdateTargetId ="RoomsAvailData",
}))
{
<div class="col-sm-4 paddingzero margintopclass">
<button type="submit" value="Search">
<img src="~/Content/images/search.png" style="cursor:pointer" alt="Search" />
</button>
</div>
}
Booking Controller Action method
public ActionResult RoomsAvail(FormCollection inputParams)
{
minRatesInventory="Some Model Data from DB";
if(Request.IsAjaxRequest())
{
return PartialView("", minRatesInventory);
}
return View(minRatesInventory);
}
In the above code snippet, Request.IsAjaxRequest() is always returning false.
EDIT
I have added jquery.unobtrusive-ajax.min.js before jQuery. It makes problem to call ajax. I have updated this and its working fine.
How would I implement AJAX validation in struts2 which lets you know if a username is available onblur? This is what I've managed so far but the docs aren't clear:
JSP:
<%# page
language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib
prefix="s"
uri="/struts-tags"%>
<%# taglib
prefix="sj"
uri="/struts-jquery-tags"%>
<!DOCTYPE html>
<html>
<head>
<sj:head jqueryui="true" />
<!-- Don't forget these 2 files!! -->
<script
src="${pageContext.request.contextPath}/struts/utils.js"
type="text/javascript"></script>
<script
src="${pageContext.request.contextPath}/struts/css_xhtml/validation.js"
type="text/javascript"></script>
<script
type="text/javascript"
src="js/register.js"></script>
<title>Register</title>
</head>
<s:url
action="loginLink"
var="loginHREF" />
<s:url
action="forgotPasswordLink"
var="forgotPasswordHREF" />
<s:url
action="Register"
var="registerHREF" />
<body>
<s:form
theme="css_xhtml"
action="Register"
onsubmit="return myValidate()">
<s:textfield
name="user.username"
label="Username"
id="uname"
required="true"
pattern="[a-zA-Z0-9_-]{5,12}"
title="5-12 Alphanumeric characters required" />
<s:textfield
name="user.email"
label="Email"
required="true" />
<s:password
id="pass1"
name="user.password"
label="Password"
required="true"
pattern="{5,12}"
title="5-12 characters" />
<s:password
id="pass2"
label="Confirm Password"
required="true"
pattern="{5,12}" />
<s:textfield
name="user.firstName"
label="First Name"
required="true" />
<s:textfield
name="user.lastName"
label="Last Name" />
<sj:datepicker
yearRange='-90:-3'
changeYear="true"
name="user.birthDate"
readonly="true"
label="Date of Birth" />
<s:submit value="Register" />
</s:form>
<s:a href="%{loginHREF}">Login</s:a>
<s:a href="%{forgotPasswordHREF}">Forgot Password</s:a>
<script>
$("#uname").blur(function() {
var fieldData = $("#uname").serialize();
fieldData = fieldData.slice(5);
//do the POST thingies
$.ajax({
type : "POST",
url : "ValidateUsername",
cache : false,
data : fieldData,
dataType : "json",
complete : function(request) {
alert("In complete");
var form = $('form');
//clear previous validation errors, if any
//StrutsUtils.clearValidationErrors(form);
//get errors from response
var text = request.responseText;
alert(text);
var errorsObject = StrutsUtils.getValidationErrors(text);
//show errors, if any
if (errorsObject.fieldErrors) {
StrutsUtils.showValidationErrors(form, errorsObject);
}
}
});
return false;
});
</script>
</body>
</html>
Action:
#Action("ValidateUsername")
#Results(value = { #Result(name = "success", type = "json"), #Result(name = "input", type = "json") })
#ParentPackage("default")
#InterceptorRef("jsonValidationWorkflowStack")
public class ValidateUsername extends ActionSupport {
private String username;
#Override
public String execute() {
return SUCCESS;
}
#Override
public void validate() {
UserService service = new UserService();
User isTaken = service.findByUsername(username);
service.close();
if (isTaken != null)
addFieldError("user.username", "That username is taken");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
The docs make it seem like struts2 will handle it for you if you simply add the json interceptor and set validate="true" in the sx:submit tag.
In register.js I check to see that password and confirmation password match.
Basically I would like it to validate even before submit is pressed. Right now On submit it validates it like any other normal form.
Edit: Also, is there a working method other than using dojo? It seems to block all my client side validation including the required attributes, js, etc.
Edit2:I ditched the dojo plugin, learnt some js and managed to put together what i have now. Now the only thing left is to display an error. Alerting the response text shows up a json string with only a username key value pair in it. Should i add another member to the action and process it to display an error message? because the StrutsUtils js is not working. addFieldError("user.username", "That username is taken"); does not modify the json result.
Basically, how can i add fielderrors to my json response?
Edit: I got my action to add my field errors to the json response by modifying the annotations as follows:
#Action("ValidateUsername")
#Results(value = {
#Result(name = "success", type = "json"),
#Result(name = "input", type = "json", params = { "ignoreHierarchy",
"false", "includeProperties",
"actionErrors.*,actionMessages.*,fieldErrors.*" }) })
#ParentPackage("default")
#InterceptorRef("jsonValidationWorkflowStack")
Now the only problem is in:
//clear previous validation errors, if any
**//StrutsUtils.clearValidationErrors(form);**
//get errors from response
var text = request.responseText;
alert(text);
**var errorsObject = StrutsUtils.getValidationErrors(text);**
//show errors, if any
if (errorsObject.fieldErrors) {
StrutsUtils.showValidationErrors(form, errorsObject);
}
None of the StrutsUtils functions are working. When i uncomment clearValidationErrors it does nothing and breaks the rest of the js code. errorsObject is empty and showValidation does nothing even though on printing my jon response i can see a field error with a message. How do i get StrutsUtils to work?
Also, is there a better way to implement my use case? I haven never learnt jquery/ajax and this is my first struts2 application.
Struts is available server-side. You are trying to call
var errorsObject = StrutsUtils.getValidationErrors(text); in the client-side.
StrutsUtils is a class and is not available on client-side/javascript.
There are various ways through which you can send errors.
Please refer my answer in the below link, on how to handle ajax request & response when using struts2.
How to get Ajax response in Struts2
Controller:
public ActionResult Edit(string temp)
{
ViewBag.Time = DateTime.Now.ToString("hh:mm:ss");
return PartialView("Edit");
}
Partial View:
#using (Ajax.BeginForm("Edit", "Home", new AjaxOptions{UpdateTargetId = "mydiv"}))
{
<input type="submit" value="Save" />
}
Index View (part of contents)
<div id="mydiv">
<span>The Time is: #ViewBag.Time</span>
</div>
#Html.Partial("Edit")
ClientValidationEnabled and UnobtrusiveJavaScriptEnabled are true
jquery.validate.min.js, jquery.validate.unobtrusive.min.js, jquery.unobtrusive-ajax.min.js, MicrosoftMvcAjax.js and MicrosoftAjax.js are added
At first, the time is shown correctly. When the Save button is clicked for the first time, time disappears and Save button is shown twice and then nothing happens except calling the Action on clicking on both buttons.
You have things kind of backwards. Try this:
Controller
public ActionResult Edit(string temp)
{
ViewBag.Time = DateTime.Now.ToString("hh:mm:ss");
return PartialView("Edit");
}
Index View
#using (Ajax.BeginForm("Edit", "Home", new AjaxOptions{UpdateTargetId = "mydiv"}))
{
<input type="submit" value="Save" />
}
#Html.Action("Edit")
Partial View (Edit)
<div id="mydiv">
<span>The Time is: #ViewBag.Time</span>
</div>
The ViewBag is only accessable at runtime (when the page initially loads) so this means if you fetch data via ajax, the viewbag in the controller action is only accessable to the partial view of that controller action (and not index.cshtml which called the action via ajax). In short (tl;dr) to be able to use the viewbag which you set in Edit action, you need to use it in the returning partialview. (and not anywhere else, because the content isnt re-rendered by the razor engine)
I set things up like so.
Very simple, but I noticed the person posting the
question and the answer had no insertion mode so I posted this lame bit of code :)
{
HttpMethod = "post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "the div youwant to update / replace"
}
My site has a concept like Skype that allow users to go "Online" and "Offline". I created a partial view that allows the user to switch mode:
#if (Convert.ToBoolean(ViewData["IsLogged"].ToString()))
{
<div id="onlineStatus">
You are currently <strong>ONLINE</strong> >>
#Html.ActionLink("Go OFFLINE", "GoOffline", "Account")
</div>
}
else
{
<div id="offlineStatus">
Ready for business >>
#Html.ActionLink("Go ONLINE", "GoOnline", "Account")
</div>
}
This is how we load the Partial View:
public ActionResult OnlineStatusCtrl()
{
if (SiteUser.IsAuthenticated)
ViewData["IsLogged"] = SiteUser.IsOnline.ToString();
return PartialView("OnlineStatusCtrl");
}
When a user clicks on the link "Go ONLINE" or "Go OFFLINE", the Controller respond as:
public ActionResult GoOnline()
{
if (SiteUser.IsAuthenticated)
SiteUser.GoOnline();
ViewData["IsLogged"] = "True";
return RedirectToAction("Index", "Home");
//return PartialView("OnlineStatusCtrl");
//return EmptyResult();
}
public ActionResult GoOffline()
{
if (SiteUser.IsAuthenticated)
SiteUser.GoOffline(true);
ViewData["IsLogged"] = "False";
return RedirectToAction("Index", "Home");
}
This works well ...but the ONLY problem is that if I am on View XXXX, and I click on "Go Online", the controller redirects me to the Index View.
I tried "return EmptyResult()" or "return PartialView("OnlineStatusCtrl") but it does just not work.
From the code, you can see that the only thing the PartialView cares about is the "ViewData['IsLogged'] value"
QUESTION:
What is the way to REFRESH a partial view without having to refresh the entire page or redirect to the main page?
Is it maybe a matter of putting an Html.Beginform() ?
Is it maybe a matter of the Controller returning something that just refresh the content of the PartialView independently from what view is holding the PV itself?
Aiaiaiaia
I still can't figure out how MVC works with PartialViews/
UPDATE
I have updated the code as x suggested and the HTML output is as follow:
<div id="divStatus">
<form action="/" data-ajax="true" data-ajax-mode="replace" data-ajax-update="#divStatus" id="form0" method="post">
<div id="offlineStatus">
Ready for business >>
Go Online
</div>
</form>
</div>
When I click on the LINK, the Controller return PartialView("_OnlineStatusCtrl"); which is hte name of the calling PV ...and the ENTIRE PAGE gets replaced.
You're going to have to use an ajax call of some sort (Microsoft ajax helpers built into MVC, or jquery/javascript ajax call.
To use Microsoft's Ajax, you can use Ajax.BeginForm or Ajax.ActionLink. Both take an AjaxOptions parameter that will allow you to set javascript functions for OnSuccess, and an UpdateTargetId to display the returned data (usually a partial view). Using this will call your action which should return a partial view. Your partial view then replaces the html element (usually a div) identified by the UpdateTargetId parameter. If you decide to go this route, make sure you reference all the proper Microsoft ajax/mvc scripts. You'll pretty much need each script with any combinations of Microsoft, Ajax, Mvc, and even unobtrusive in the name.
Here's an example of one of my ajax forms (modified slightly for simplicity)
<% using(Ajax.BeginForm("addAttribute", new { id = Model.PersonId, attributeId = item.AttributeId }, new AjaxOptions { UpdateTargetId = "myTargetId", OnSuccess = "initForm" })) { %>
<input type="submit" value="Ok" class="editMode okButton" disabled="disabled" />
<input type="button" class="editMode cancelButton" value="Cancel" />
<br />
<input type="button" value="Add" class="addButton" />
<% } %>
I have a div with an id of "myTargetId" (for this example) that will be updated with the returned partial view.
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