My problem is the following:
I'm using client validation function of the MVC 2.0 framework.
Everything is nice, when I use the validation in a simple form.
But when I use an Ajax form, and I update the fields of the ajax form, the client validation doesn't work.
I think about, I have to refresh the validation after the ajax call but I don't know how I should do it.
Anybody can help me?
this happens because the window.mvcClientValidationMetadata fills in a different "scope" than the jquery validation or mvc client validation functions. I have solved this with jquery validation adding the following line before the ajax.begin form. Like this:
<div id="result"></div>
<% Html.EnableClientValidation(); %>
<% using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
// here goes the form
<input type="submit" value="Create" />
<% } %>
this is the required code that needs to be added:
<script type="text/javascript">
function RefreshClientValidationMetadata() {
var allFormOptions = window.mvcClientValidationMetadata;
if (allFormOptions) {
while (allFormOptions.length > 0) {
var thisFormOptions = allFormOptions.pop();
__MVC_EnableClientValidation(thisFormOptions);
}
}
}
RefreshClientValidationMetadata();
</script>
Of course the function RefreshClientValidationMetadata() can be added in any place.
Hope this help!
Try this:
$(document).ajaxComplete(function () {
$.validator.unobtrusive.parse(document);
});
Related
I tried to use google federated login function to retrieve user info in order to implement an one-click registration functionality for my website.
I have retrieved all the information on the client side. I used several hidden input fields to store the values for the parameters like name,email, etc. However, when I accessed these fields from code behind, I got empty values.
Here are the steps I took to inspect the problem:
1. I have made sure that each input field has the [runat="server"] tag and have made sure that all the values are correctly returned from google.
2. I have made sure that all the input fields are inside the form
I am wondering if it is because I did not submit the form once I clicked the google+ login button, the button is as the following:
<div id="signin-button" class="slidingDiv">
<div class="g-signin" data-callback="loginFinishedCallback"
data-approvalprompt="force"
data-clientid="....."
data-scope=" https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me "
data-height="short"
data-cookiepolicy="single_host_origin"
>
</div>
</div>
This button will lead me to other functions that verify about my credentials and return the parameters I request. I am wondering how I could modify it so that I could make the form be submitted once I click on this button?
If it is not caused by this issue, could anyone think of other possible reasons why I could not get the hidden input value from code behind?
Here is my callback function
function loginFinishedCallback(authResult) {
if (authResult) {
if (authResult['error'] == undefined) {
gapi.auth.setToken(authResult);
toggleElement('signin-button'); /
getInfo();
document.getElementById('Button').click();
} else {
console.log('An error occurred');
}
} else {
console.log('Empty authResult');
}
}
getInfo will get all the google plus information , and button.click() is supposed to retrieve the information from the client side to the server side
The Google+ Sign-In button currently does not POST form data but instead passes the authorization code and access token back to the page in the callback function configured in the button. You might be able to do something clever like use JavaScript to update a hidden field with the content (which you might already be doing?) and then use the data from that hidden field for OAuth 2 code exchange on your server side.
An alternate approach is used in the Google+ C# Quick Start sample. What that sample does is use an API endpoint to POST the authorization code that later is exchanged server-side for the OAuth 2 credentials.
I have thrown together some code that will pass the authorization code for authorizing your backend. It consists of the form frontend:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="fedLogin.aspx.cs" Inherits="GPlusQuickstartCsharp.fedLogin" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<script type="text/javascript">
var confirms = 0;
function loginFinishedCallback(result) {
console.log(result);
if (result.access_token != null) {
gapi.client.load('plus', 'v1', function(){
gapi.client.load('oauth2', 'v2', function () {
gapi.client.plus.people.get({ userId: 'me' }).execute(
function (resp) {
document.getElementById('name').value = resp.displayName;
confirms += 1;
if (confirms > 1) {
document.getElementById('form1').submit();
}
});
});
gapi.client.load('oauth2', 'v2', function () {
gapi.client.oauth2.userinfo.get().execute(
function (resp) {
document.getElementById('email').value = resp.email;
confirms += 1;
if (confirms > 1) {
document.getElementById('form1').submit();
}
});
});
});
document.getElementById('code').value = result.code;
}
}
</script>
<div id="signin-button" class="slidingDiv">
<div class="g-signin" data-callback="loginFinishedCallback"
data-clientid="....apps.googleusercontent.com"
data-scope="https://www.googleapis.com/auth/userinfo.email"
data-height="short"
data-cookiepolicy="single_host_origin"
>
</div>
</div>
<form id="form1" runat="server" method="post">
<div>
<input type="hidden" name="code" id="code" />
<input type="hidden" name="email" id="email" />
<input type="hidden" name="name" id="name" />
</div>
</form>
</body>
<script type="text/javascript">
(function () {
var po = document.createElement('script');
po.type = 'text/javascript'; po.async = true;
po.src = 'https://plus.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
</html>
And the code behind [C#]:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace GPlusQuickstartCsharp
{
public partial class fedLogin : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request["code"] != null)
{
// Perform code exchange here
var result = ManualCodeExchanger.ExchangeCode(Request["code"]);
}
}
}
}
If you put a breakpoint at the var result = ... line, you can see the request variables in your immediate window, e.g.:
Request["code"]
"4/xUgz-_zWFAgpq4Kbfas66pV0oWJ8........."
Request["email"]
"gguuss#gmail.com"
Request["name"]
"Gus Class (Gus)"
Hope this helps!
Note: Although you need the client ID and client secret to exchange the one-time-code as demonstrated in the code, it's a best practice to protect it as best you can. I'm using a POST in an effort to protect the code in the form to help but you should also use https whenever you are passing around credentials.
I'm trying to convert a form from synchronous to asynchronous using the Ajax.BeginForm helper method in MVC 4.
In my view I have:
#{
ViewBag.Title = "Users > Edit";
var options = new AjaxOptions()
{
Url = Url.Action("Edit", "User"),
LoadingElementId = "saving",
LoadingElementDuration = 2000,
Confirm = "Are you sure you want to save this User?"
};
}
<div id="saving" style="display:none; color:Red; font-weight: bold">
<p>Saving...</p>
</div>
#using (Ajax.BeginForm(options))
{
#Html.ValidationSummary(true)
<fieldset>
.... FIELDS ...
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
When the submit button is clicked a complete postback is being executed. My action method looks like this:
[HttpPost]
public ActionResult Edit(User user)
{
if (ModelState.IsValid)
{
_repository.Save(user);
TempData["message"] = String.Format("{0} has been saved.", user.Username);
}
return View(user);
}
Is there something I'm missing? Has the MVC 4 current release got a few problems?
In my Web.Config I do have ClientValidationEnabled and UnobtrusiveJavaScriptEnabled set to true.
I also have these specified in my _Layout.cshtml:
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
Is there something I'm missing?
Maybe you are missing the unobtrusive ajax script:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
if i am understood correct, you are trying to post the data to controller, after successful you need to go to home page ?? if not can you clarify. so that will try to help you
if (ModelState.IsValid)
{
_repository.Save(user);
TempData["message"] = String.Format("{0} has been saved.", user.Username);
return RedirectToAction("yourActionToRedirect"); // after succesfull it will go to the index view
}
I had the same kind of problem... I've updated all the js files with nuget package console.
just my 2 cents, but also at the time of writing, the jquery.unobtrusive.ajax file does contain calls to the deprecated jquery function '.live' (=> it's deleted from jquery 1.9+ version) jquery live
I think there are like 4 occurrences that you'll have to change with .on, now it works fine ;-)
In my code I am using a partial view (call it PV1)
<div id="div_1">
<% Html.Partial("PV1", Model); %>
</div>
and in that partial view I am using "Ajax.BeginForm" to redirect it to a particular action, hence it is doing so ...
using (Ajax.BeginForm("action1", "Forms", null, new AjaxOptions { UpdateTargetId = "div_1" }, new { id = "form1" }))
{
Response.write("I am here.");
}
public ActionResult action1(XYZ Model)
{
//
return PartialView("PV1", Model);
}
at the last line of action I am again calling the same partial 'PV1', hence it is doing this too ...
but when rendering the view it don't print or do the steps written with in partial view, it override them with and show nothing ...
Html.Partial actually returns the result of rendering the view, you want to do <%= Html.Partial() %> or <% Html.RenderPartial(); %>
Html.Partial() returns the Html and thusly must be output on the page via <%= %> and Html.RenderPartial() uses Response.Write to output onto the page and can be used with <% %>.
This is not what you would use Ajax.BeginForm for. That helper is used to create actual <form> tags that will later be submitted to the server using MVC's unobtrusive ajax (so you still need some kind of a trigger action - a button, javascript - anything that submits the form).
I'm am not very clear on what you're trying to achieve. If you want to load a partial view with ajax, I would suggest using something like jQuery's ajax load method.
I am struggling to get to grips with a particular form setup in my asp.net MVC application.
Currently I have a page which displays a chunk of data. On this page is a simple form that calls into an action method that returns a partialview when posted (through ajax - jform).
This is all very well until I try and add paging support to the search results.
I have a chunk of code that that will paginate an IQueryable, but Im not sure how to implement this in my current setup.
Heres some code:
[Authorize]
public ActionResult AssetSearch(string RoomID, string type, string keyword, string risks)
{
//check values passed in
Guid? r = null;
if (RoomID != "Any" && RoomID != null)
r = new Guid(RoomID);
string t = type == "Any" ? null : type;
string risk = risks == "Any" ? null : risks;
var assets = surveyRepository.GetAssetsSearch(r, t, keyword, risk);
if (Request.IsAjaxRequest())
{
return PartialView("AssetListControl", assets);
}
else
{
return View("AssetListControl", assets);
}
}
This action method returns a partial view which gets rendered out in a div through the following jquery.
$(document).ready(function() {
$("#searchForm").submit(function() {
$("#searchForm").ajaxSubmit({ target: '#results', beforeSubmit: PreSub, success: Success });
return false;
});
});
function Success(responseText, statusText) {
$("#loadingMessage").html("done");
$('#resultsTable').tablesorter();
$("#results").slideDown("slow");
}
function PreSub(formData, jqForm, options) {
$("#loadingMessage").html("loading...").fadeIn();
$("#results").slideUp("fast");
return true;
}
And my form looks as follows:
<form id="searchForm" action="<%=Url.Action("AssetSearch") %>" method="post">
<fieldset>
<label for="RoomID">
Room Name</label>
<%= Html.DropDownList("RoomID") %>
<label for="Type">
Asset Type</label>
<%= Html.DropDownList("Type") %>
<label for="Risks">
Risk Level</label>
<%= Html.DropDownList("Risks") %>
<label for="Keyword">
Keyword</label>
<%= Html.TextBox("Keyword") %>
<input type="submit" name="sumbit" id="searchBtn" value="Search" />
</fieldset>
</form>
Sorry for the code overload :-)
I have a feeling that I have configured my controller and view in such a way that paging won't be easy to implement. All advice welcome!
Thanks in advance!
Ok, so I managed to get it working with AJAX and POST in a not so attractive way.
Firstly, I dropped a couple of anchor tags in my paged results partial view that, if there are previous or next pages, show up. These links fire off a javascript function and pass a page value. The navigation looks as follows:
<% if (Model.HasPreviousPage)
{ %>
Back
<%} %>
<% if (Model.HasNextPage)
{ %>
Forward
<%} %>
The function looks as follows:
function PageResults(page) {
var form = document.forms["searchForm"];
form.elements["page"].value = page;
$("#searchForm").ajaxSubmit({ target: '#results', beforeSubmit: PreSub, success: Success });
return false;
}
I have also tweaked my controller to accept a page parameter, which is used to retrieve the correct set of results:
var paginated = new PaginatedList<Asset>(assets, Page ?? 0, 10);
This seems to do the trick, although its not great :)
i'm wanted to perform some ajax calls in a certain way.
I have a page. In this page are 2 ViewUserControls, say control1 and control2.
control1 has a list of Ajax.ActionLinks that call control2 like this:
<%= Ajax.ActionLink(page.Name, "PageDetails", new { pageSysName = page.SysName }, new AjaxOptions { UpdateTargetId = "pageEdit" })%>
control2 has an Ajax form which updates fine. The Ajax.BeginForm method looks like this:
Ajax.BeginForm("SavePage", "Admin", new AjaxOptions { UpdateTargetId = "pageEditUpdated" })
When a user hits the Save button, it currently updates a div called pageEditUpdated with a basic Content("updated") return type from the Controller.
The part i'm stumped on is how to update control2 to reflect the new changes.
To sum it up, a Page has 2 controls. I'd like control2 to refresh itself and also update a div to notify the user that the update has been performed.
Have your SavePage method return a partial that reflects the updated form contents, including the update message. Have the update target be the "inner container" of the form.
<% Ajax.BeginForm("SavePage", "Admin", new AjaxOptions { UpdateTargetId = "innerForm" }) { %}
<div id="innerForm">
<% Html.RenderPartial( "EditPageContents" ) %>
</div>
<% } %>
Your save action should then return
updatedModel.UpdateMessage = "updated";
return PartialView( "EditPageContents", updateModel );
and your partial view should have
<% if (!string.IsNullOrEmpty( UpdateMesage )) { %>
<%= Html.Encode( UpdateMessage ) %>
<% } %>
Honestly, though, this would be a lot easier using jQuery to post the form via AJAX:
$(function() {
$('form').submit( function() {
$.post( $(this).attr('action'), $(this).serialize(), function(data) {
$('#updateMessage').html(data).show();
});
return false;
});
});
I have to second tvanfosson's comment (I'd vote for him, but my reputation apparently isn't high enough yet). At any rate, when I integrated Ajax functionality with my MVC site I found the Microsoft provided Ajax methods to be fairly clunky. So instead I switched to using the jQuery.form plugin (good examples here). I found it made things much easier to work with. I just created MVC user controls for the section of page I wanted to be ajax, and just reloaded that user control as neccessary.