Post data to controller with JQuery via login screen - asp.net-mvc

I have a section in my ASP.NET MVC3 website where a user can click a button to add an entry to their 'Saved Items' section in their account. This is done via a JQuery Ajax request, which works well if they're logged in. If they're not logged in, I'd like them to be redirected to a login page, and then automatically have the entry added to their Saved Items section.
I have all the parts working seperately - i.e. when the button is clicked, if not logged in, the login box displays. The login popup also works successfully. The problem is trying to seamlessly do all things at once. Here is the code I have so far:
Click event for Save button - checks to see if user logged in along the way:
var loggedIn = false;
$(document).ready(function () {
$('a#saveSearch').live('click', function (event) {
$.get('#Url.Action("IsLoggedIn", "Account", null)', function (response) {
if (response == "True")
loggedIn = true;
else
loggedIn = false;
});
if (loggedIn){
SaveSearch();
}
else{
$('#dialog').dialog('open');
SaveSearch(); //don't think this is correct because it hits this line before login is complete
}
});
Function to save to database:
function SaveSearch(){
var url = '#Url.Action("SaveSearch", "User")';
$.ajax({
url: url,
type: 'POST',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
json: "#Html.Raw(Session["MyFormString"].ToString())"
}),
success: function (data) {
$('a#saveSearch').attr('disabled', "disabled");
$('div#savedResponse').html('<p>Search saved to user account</p>');
},
error: function () {
}
});
}
});
JQuery UI dialog popup:
$(function () {
$('#dialog').dialog({
autoOpen: false,
width: 400,
resizable: false,
title: 'Login',
modal: true,
open: function(event, ui) {
$(this).load("#Url.Action("Logon", "Account", null)");
},
buttons: {
"Close": function () {
$(this).dialog("close");
}
}
});
I think there is something fundamental that is wrong with my code, because this way, the login popup appears for just a second and then disappears straight away. It looks like I need to get it to stop advancing through the code until the login has been completed.
Any advice or help to get this going would be appreciated.

I would imagine your issue might be related to:
$.get('#Url.Action("IsLoggedIn", "Account", null)', function (response) {
if (response == "True")
loggedIn = true;
else
loggedIn = false;
});
if (loggedIn){
SaveSearch();
}
else{
$('#dialog').dialog('open');
SaveSearch(); //don't think this is correct because it hits this line before login is complete
}
The $.get call is async, which means the latter code:
if (loggedIn){
Is being executed before the server has responded. You need to put that code within your response callback:
$.get('#Url.Action("IsLoggedIn", "Account", null)', function (response) {
if (response == "True")
loggedIn = true;
else
loggedIn = false;
if (loggedIn){
SaveSearch();
}
else{
$('#dialog').dialog('open');
SaveSearch(); //don't think this is correct because it hits this line before login is complete
}
});

Try and add a close callback function to your modal, then the code will only be done as soon as the modal is closed and all the login have been done sucessfully. See comments in your code
$(document).ready(function () {
$('a#saveSearch').live('click', function (event) {
$.get('#Url.Action("IsLoggedIn", "Account", null)', function (response) {
if (response == "True")
loggedIn = true;
else
loggedIn = false;
});
if (loggedIn){
SaveSearch();
}
else{
//in this dialog, add a close handler,then add the SaveSearch(); function in that handler
$('#dialog').dialog('open');
}
});

Related

Asp.net Mvc jquery ajax?

I have links like following.
Deneme Müşteri 2
Deneme Müşteri 2
I want to use jquery ajax post like this:
$(".customer_details").click(function () {
$.ajax({
url: $(this).attr("href"),
type: 'POST',
beforeSend: function () {
},
complete: function () {
},
success: function (result) {
$("#customer_operations_container").html(result);
},
error: function (result) {
alert("Hata!");
}
}); //end ajax
});
Or this:
$(".customer_details").click(function () {
$("#customer_operations_container").load($(this).attr("href"));
});
And Action Method
public ActionResult _EditCustomer(int CustomerId)
{
// get customer from db by customer id.
return PartialView(customer);
}
But I cant do what I wanted. When I click to link, PartialView does not load. It is opening as a new page without its parent. I tried prevent.Default but result is the same.
How can I load the partialView to into a div?
Note: If I use link like this <a href="#"> it works.
Thanks.
Maybe the problem is with the actionresult, try with Content to see if that changes anything.
public ActionResult _EditCustomer(int CustomerId)
{
// get customer from db by customer id.
return Content(customer.ToString());
}
Try one of these...
$(".customer_details").click(function (e) {
e.preventDefault()
$.ajax({
url: $(this).attr("href"),
//I think you want a GET here? Right?
type: 'GET',
beforeSend: function () {
},
complete: function () {
},
success: function (result) {
$("#customer_operations_container").html(result);
},
error: function (result) {
alert("Hata!");
}
}); //end ajax
});
Or
$(".customer_details").click(function (e) {
e.preventDefault();
$("#customer_operations_container").load($(this).attr("href"));
});
Or
$(".customer_details").click(function (e) {
e.preventDefault();
$.get($(this).attr("href"), function(data) {
$("#customer_operations_container").html(data);
});
});
If none of this works, check if there's any js errors
The problem is when you click on the link you already start navigation to it. So just use e.preventDefault() or return false from the click method to prevent the default behavior
$(".customer_details").click(function (e) {
e.preventDefault();
...
}
This should help you out:
$.ajax({
url: $(this).attr("href"),
type: 'POST',
beforeSend: function () {
},
complete: function () {
},
success: function (result) {
$("#customer_operations_container").html(result);
},
error: function (result) {
alert("Hata!");
}
}); //end ajax
return false;
The only thing you where missing is the prevention of A tag working. By returning false your custom event is called and the default event is not executed.
Try this
$(function(){
$(".customer_details").click(function (e) {
e.preventDefault();
});
});
Using ready event
Demo: http://jsfiddle.net/hdqDZ/

Jquery dialog close funcationality

I am having a Jquery dialog with two buttons Add and Cancel. User will input few fields and on pressing Add button, I am doing UI modifications and validations. After all the operations are done, I am closing the dialog. But issue is, even though I am closing the dialog after save and other operations, but the dialog is getting closed before the operations gets completed.
Below is my Jquery dialog code,
dlg.dialog({
height:300,
width:600,
modal:true,
autoOpen:true,
title: "Add Property",
closeOnEscape:true,
buttons: {
"Cancel": function() {
$(this).dialog("close");
},
"Create Property": function() {
//Validate Property
// Save Property
$(this).dialog("close");
}
}
}
});
function save() {
$.ajax({
type: 'POST',
url: ServiceUrl,
data: parameter,
success : function(data) {
// Convert the response text to JSON format
var jsonData = eval('(' + data + ')');
if (jsonData.results) {
// success
}
}
});
};
In above code I am executing $(this).dialog("close"); after validate and save function but my dialog is getting closed , before these function finishes. This behavior doesn't happen if I execute line by line by keeping breakpoints in firebug. Please help in resolving and help me in understanding. Thanks in advance.
Since the .ajax() call(s) are asynchronous, the $(this).dialog("close"); does not wait for the .ajax() call to finish. Put the dlg.dialog("close"); inside the success of the .ajax() call after you see that the save/validations were successful.
dlg.dialog({
height:300,
width:600,
modal:true,
autoOpen:true,
title: "Add Property",
closeOnEscape:true,
buttons: {
"Cancel": function() {
$(this).dialog("close");
},
"Create Property": function() {
//Validate Property
// Save Property
$.ajax({
success: function (response) {
//test to see if the response is successful...then
dlg.dialog("close");
},
error: function (xhr, status, error) {
//code for error condition - not sure if $(this).dialog("close"); would be here.
}
})
}
}
}
});
Your logic should look something like:
dlg.dialog({
height:300,
width:600,
modal:true,
autoOpen:true,
title: "Add Property",
closeOnEscape:true,
buttons: {
"Cancel": function() {
$(this).dialog("close");
},
"Create Property": function() {
$.ajax({//Validate request
...
success:function(response){
$.ajax({//Save request
...
success:function(response){
//close the dialog here
}
});
}
});
}
}
}
});
Either you can chain your ajax calls like this, or you can make them asynchronous by passing an async:false option.
I understand the need for a global "save" function, as it eliminates the need to write the same script over and over again.
Try doing something like this:
dlg.dialog({
height: 300,
width: 600,
modal: true,
autoOpen: true,
title: "Add Property",
closeOnEscape: true,
buttons: {
"Cancel": function () {
$(this).dialog("close");
},
"Create Property": function () {
save(true); //!!!
}
}
});
And then:
function save() {
$.ajax({
type: 'POST',
url: ServiceUrl,
data: parameter,
success: function (data) {
// Convert the response text to JSON format
var jsonData = eval('(' + data + ')');
if (jsonData.results) {
//!!!! Then close the dialog
dlg.dialog("close") //!!!!
}
}
});
}
This way, your close function is not called until the AJAX response is received.
EDIT: I would also set the dlg variable and the save() function-name as globals by attaching them to the window object like so:
window.dlg = $("#myDialogElement");
window.save = function () {
//function stuff here
}
This will ensure they're always available.

Why are no validation errors shown with an Ajax form in my MVC?

What is wrong if no validation errors are shown when the submitted data is null/empty? An error should be shown.
In the code block result.success == false, should I reload the view or tell jQuery to invalidate my model?
From my Post action in the controller I return the model errors so I have them on the client side.
What should I do now?
I am using MVC 3.0 with latest jQuery/UI 1.7.2/1.8.20:
<script type="text/javascript">
$(document).ready(function () {
// the div holds the html content
var $dialog = $('<div></div>')
.dialog({
autoOpen: false,
title: 'This is the dialogs title',
height: 400,
width: 400,
modal: true,
resizable: false,
hide: "fade",
show: "fade",
open: function (event, ui) {
$(this).load('#Url.Action("Create")');
},
buttons: {
"Save": function () {
var form = $('form', this);
$.ajax({
url: $(form).attr('action'),
type: 'POST',
data: form.serialize(),
dataType: 'json',
success: function (result) {
// debugger;
if (result.success) {
$dialog.dialog("close");
// Update UI
}
else {
// Reload the dialog to show model/validation errors
} // else end
} // success end
}); // Ajax post end
},
"Close": function () {
$(this).dialog("close");
}
} // no comma
});
$('#CreateTemplate').click(function () {
$dialog.dialog('open');
// prevent the default action, e.g., following a link
return false;
});
});
</script>
my form is:
#using (Html.BeginForm("JsonCreate", "Template"))
{
<p class="editor-label">#Html.LabelFor(model => model.Name)</p>
<p class="editor-field">#Html.EditorFor(model => model.Name)</p>
<p class="editor-field">#Html.ValidationMessageFor(model => model.Name)</p>
}
My controller is:
[HttpGet]
public ActionResult Create()
{
return PartialView();
}
[HttpPost]
public ActionResult JsonCreate(Template template)
{
if (ModelState.IsValid)
{
_templateDataProvider.AddTemplate(template);
// success == true should be asked on client side and then ???
return Json(new { success = true });
}
// return the same view with model when errors exist
return PartialView(template);
}
The working version is:
I changed this in my $.ajax request:
// dataType: 'json', do not define the dataType let the jQuery infer the type !
data: form.serialize(),
success: function (result)
{
debugger;
if (result.success) {
$dialog.dialog("close");
// Update UI with Json data
}
else {
// Reload the dialog with the form to show model/validation errors
$dialog.html(result);
}
} // success end
The Post action has to look like this:
[HttpPost]
public ActionResult JsonCreate(Template template)
{
if (!ModelState.IsValid) {
return PartialView("Create", template);
_templateDataProvider.AddTemplate(template);
return Json(new { success = true });
}
}
Either return the partialview which is the form (success == false) or return the JSON which is success == true.
Someone could still return a list of items to update the UI on client side:
return Json(new { success = true, items = list});
You got to make sure you are returning a JSON data and not html or any other kind of data. Use the browsers console to find out more about your ajax request and response to be sure that you are getting the right response, as you expect.
well, the mistake I see is --
you are doing a return in the controller, you are supposed to do a
Response.Write(Json(new { success = true, items = list}));

Changing link destination with the pagebeforechange event and keeping it out of the history?

I am working on a PhoneGap application that uses jQuery Mobile (jQM). This application has areas that will require the user to be authenticated. So I'm using jQM's pagebeforechange to determine if the user needs to authenticate before viewing the page they have requested. If so, I send them to a login page.
I want to keep the login page out of jQM's history tracking. That is, if the user is presented with the login page, but decides to press "cancel," I want the application to go back to the previous page and not have a "next" page in the history; the "previous page" would be at the top of the history stack.
Here's how I am handling the login page redirection:
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/someRestrictedPage/)) {
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "myLogin.html";
}
});
For the cancel button of my login page I am doing:
$loginCancelButton.bind('click', function() {
var prevPage = $.mobile.urlHistory.getPrev();
if (typeof prevPage !== 'undefined') {
$.mobile.changePage(prevPage.url, {
changeHash: false,
reverse: true,
transition: "pop"
});
}
});
However, when I do this, I end up with a $.mobile.urlHistory.stack with three elements:
[ {"index"}, {"login"}, {"index"} ]
How do I manage intercepting page changes to redirect to a login form when necessary, but not create an "invalid" navigation history?
looking at the jquery docs it mentions that pagebeforeload event needs to be stopped. and then call the data.deferred (resolve or reject).
try changing it to:
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/someRestrictedPage/)) {
e.preventDefault()
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "myLogin.html";
}
data.deferred.resolve(/* url */, data.options)
});
A solution for the initial problem could be something like:
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/ your regex /gi))
{
if (!check_login())
{
e.preventDefault();
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "#SignIn";
$.mobile.changePage("#SignIn");
}
//data.deferred.resolve('#SignIn', data.options);
}
});
That worked for me just fine.
VeXii's solution seemed to work for me. By simply removing
data.deferred.resolve('#SignIn', data.options);
and
e.preventDefault();
On jquery mobile 1.3...
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/index/)) {
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "#login";
}
});

how to redirect to a view on $.AJAX complete - asp.net mvc 3

Ok..i want to redirect a user after the validation check using $.AJAX to a peritcular view... how do i do that ? .. pleae help...
here is my $.AJAX code... EX: i want user redirected to "/Home/Movies" controller action...
if not logged in stay on the same page...
<script type="text/javascript">
$('#btnLogin').click(function () {
var email = $('#Email').val();
var Password = $('#Password').val();
var postdata =
{
"Email": email,
"Password": Password
};
$('.Loading').fadeIn(50);
$.ajax({
url: '#Url.Action("CheckLogin","Home")',
data: postdata,
success: function (msg) {
var data = msg.split(':');
$('#Result').html(data[0]);
$('.Loading').fadeOut(50);
},
error: function (data) {
$('#Result').html(data);
$('.Loading').fadeOut(50);
}
});
});
</script>
here is my controller action which is used for checking Login details...
public ContentResult CheckLogin(Users checkuser)
{
if (db.CheckUserLoginDetails(checkuser.Email, checkuser.Password))
{
return Content("Login Successful:" + checkuser.Email);
}
else
{
return Content("Login UnSuccessful");
}
}
also how can i pass a returned results from this view to another view.. in this exmaple if the user is logged in i want to show his email id on the redirected page which is lets say "/home/Movies"
thx in advance
Show your loading image before ajax request, and hide on success or error handlers.
add <div class="loading">Loading...</div> to your markup
$('.loading').fadeIn(50);
$.ajax({
url: '#Url.Action("CheckLogin","Home")',
data: postdata,
success: function (msg) {
$('#Result').html(msg);
$('.loading').fadeOut(50);
},
error: function (data) {
$('#Result').html(msg);
$('.loading').fadeOut(50);
}
});
Take a look at the ajaxStart() and ajaxStop() event handlers in jQuery. You could use these to show and hide a layer with a gif-animation.
http://api.jquery.com/ajaxStart/
http://api.jquery.com/ajaxStop/
use beforSend and complete attributes.
$.ajax({
url: '#Url.Action("CheckLogin","Home")',
data: postdata,
success: function (msg) {
$('#Result').html(msg);
},
error: function (data) {
$('#Result').html(msg);
},
beforeSend: function() {
$("body").append("<div class=\"ajaxLoader\" id=\"ajaxLoader"\"><div class=\"ajaxAnimation\"></div></div>");
$("#ajaxLoader").hide();
$("#ajaxLoader").fadeIn('fast');
},
complete: function() {
$("#ajaxLoader").remove();
}
});
And specify animation with css
.ajaxAnimation {
background-image: url('images/ajax-loader.gif');
background-repeat: no-repeat;
background-position: center center;
}

Resources