This is my first Ajax call, and I am really confused about what to do.
I am using ASP.NET MVC, Identity to register users in my website. Once the user is registered, I send him an email to confirm their email address.
Here is my register Action Method:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email.Trim(), Email = model.Email.Trim(), FirstName = model.FirstName.Trim(), LastName = model.LastName.Trim() };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// Send an email with this link
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
Email email = _emailBuilder.BuildConfirmationEmail(new MailAddress(model.Email.Trim(), model.FirstName.Trim() + " " + model.LastName.Trim()), callbackUrl, model.FirstName.Trim());
Session[SessionKeys.NewAccountConfirmationEmail.ToString()] = email;
await _emailService.SendEmailAsync(email);
return RedirectToAction("NewAccountCheckYourEmail");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay the form
return View(model);
}
The register method sends the confirmation email and redirects to NewAccountCheckYourEmail View and the user sees this page:
and here is the Action method to redirect users to confirm your email page
[AllowAnonymous]
public ViewResult NewAccountCheckYourEmail()
{
return View();
}
What I want to do is to store the email in the user session, so if the user clicks on resending the email, I resend the email.
I want to make an ajax call, so when the user clicks on resend link, it posts back to the controller, gets the email from the user session, resends it and redisplays the same view.
And I am not sure how to do this
What I have tried is to make this AJAX call:
$("#ResendEmailLink").click(function () {
$.ajax({
url: "/Account/NewAccountCheckYouEmail",
datatype: "text",
type: "POST",
success: function (data) {
$('#testarea').html("All OK");
},
error: function () {
$("#testarea").html("ERROR");
}
});
});
And I want it to hit this Action Method:
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> NewAccountCheckYourEmail()
{
Email email = Session[SessionKeys.NewAccountConfirmationEmail.ToString()] as Email;
await _emailService.SendEmailAsync(email);
return View();
}
But since I already have another Action method with the same name, I cannot add it... I guess what I am trying to do does not make much sense, any suggestion on a reasonable approach to achieve this?
As #Stephen Muecke pointed out to return Json data, so this basic change should work.
Resend Email Script:
$("#ResendEmailLink").click(function () {
$.ajax({
url: "/Account/ResendEmailToUser",
datatype:'json',
type: "POST",
success: function (data) {
if(data) { $('#testarea').html(data.Message) };
},
error: function () {
$("#testarea").html("ERROR");
}
});
});
Resend Email Action Method:
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> ResendEmailToUser()
{
Email email = Session[SessionKeys.NewAccountConfirmationEmail.ToString()] as Email;
await _emailService.SendEmailAsync(email);
var jsonData = new { Message = "Done!, We have Resend the Email" };
return Json(jsonData);
}
Related
I'm trying to get Selected Item from drop down list populated by SQL db and pass it to an onclick event of a button
<th>Select Club</th>
<td>#Html.DropDownList("Clubs", new SelectList(Model.Clubs.Select(x => x.Name)), "Select Club")</td>
<input type="button" onclick="AssignPlayertoClub(#Model.Player.ID,"Clubs.SelectedValue")"/> //<-- Selected Value here
So signature of AssignPlayertoClub(ID,Club) is this. I read a lot of answers on this issue but nothing fixes mine as most of them use Viewbag
This is my method in Controller Method to be called onClick
[HttpPost]
public async Task<ActionResult> AssignPlayertoClub(int ID,Club club)
{
await playerRepo.AssignPlayer(ID, club);
return RedirectToAction("Index");
}
I'm using JQuery Ajax to call the controller method like this
function AssignPlayertoClub(Id, club) {
$.ajax({
url: '/Player/AssignPlayertoClub',
type: 'POST',
data: { Id: Id, club: club },
success: function (data) {
window.location.href = data;
}
}).done(() => alert("Player Assigned"));
}
If any other code is required. Let me know
Not sure what your Club looks like. Suppose we define the Club as below :
public class Club
{
public int Id{get;set;}
public string Name {get;set;}
}
Firstly, I would suggest you using a Club.Id to identity the option:
<td>
#Html.DropDownList("Clubs", new SelectList(Model.Clubs,"Id","Name"), "Select Club")
</td>
Now we need to get the current selected value when clicking the submit button. According to the MDN, we could get the current club's Id in the following way:
<input type="button" onclick="var selected=Clubs.options[Clubs.selectedIndex].value;AssignPlayertoClub(#Model.Player.ID,selected)"/> //<-- Selected Value here
Lastly, your server is expecting an instance of Club from client side. That's not safe. It's possible that an user fakes a club name and then harm your system. A safe way is to receive an Club.Id instead of the whole Club instance. To fix that, make the method accept a parameter of Club.Id:
[HttpPost]
public async Task<ActionResult> AssignPlayertoClub(int ID,Id club)
{
var club = await clubRepo.FindAsync(Id);
await playerRepo.AssignPlayer(ID, club);
return RedirectToAction("Index");
}
[Another approach]: send an instance of club instead of club's Id (NOT SAFE)
function getClubs(){
var x = document.querySelectorAll("#Clubs option");
var clubs = [];
x.forEach(i => {
var value = i.getAttribute("value");
var text = i.textContent;
if(value !="") { clubs.push({id: value, name: text}); }
});
return clubs;
}
function AssignPlayertoClub(Id, clubId) {
var clubs = getClubs();
$.ajax({
url: '/Player/AssignPlayertoClub',
type: 'POST',
data: { Id: Id, club :clubs[clubId]},
success: function (data) {
window.location.href = data;
}
}).done(() => alert("Player Assigned"));
}
The server side action method is the same as yours :
[HttpPost]
public async Task<ActionResult> AssignPlayertoClub(int ID,Club club)
{
...
}
I am trying to do an ajax request and depending on the ajax request results I will allow the form to submit to the controller. However everytime the ajax request runs I get the error message.
Here is my javascript function:
function CheckForValidation(e) {
var scholarshipRequest = $("#scholars").val();
var aidYearRequest = $("#aidYear").val();
var amountRequest = $("#amount").val();
$.ajax({
type: "POST",
url: '#Url.Action("Validate_ScholarshipRequest", "RequestController")',
data: {
scholarshipId: scholarshipRequest,
aidYear: aidYearRequest,
amount: amountRequest
}
}).success(function(response) {
if (!response.success) {
e.preventDefault();
alert(success);
} else {
e.preventDefault();
}
}).error(function() {
e.preventDefault();
alert("Error on Submission");
});
}
This function is called from here:
$("#SubmitTutorRequestFrm").submit(function(e) {
e.PreventDefault();
CheckForValidation(e);
});
I try to debug the code and put a breakpoint on Validate_ScholarshipRequest but that method never gets called. The method signature is:
public ActionResult Validate_ScholarshipRequest(string scholarshipId, string aidYear, string amount)
This is the start of my form:
#using (Html.BeginForm("SubmitScholarshipRequest", "Request", FormMethod.Post, new { id = "SubmitTutorRequestFrm" }))
Just to get this officially answered and "closed", this was caused by a syntax-error:
url: '#Url.Action("Validate_ScholarshipRequest", "RequestController")',
Controller should not be included in the controller name. The correct action would then be:
url: '#Url.Action("Validate_ScholarshipRequest", "Request")',
View
$("#button").click(function () {
$('#result').html("Processing...");
$.ajax({
url: '#Url.Action("GetData", "Json")',
async: true,
dataType: "json",
type: "GET",
success: function (data) {
$('#result').html(data);
},
});
return false;
});
Controller
public class JsonController : AsyncController
{
[HttpGet]
public async Task<JsonResult> GetData()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:8000/myservice.svc/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("GetData");
var result = await response.Content.ReadAsAsync<JSONResponse>();
return Json(result, JsonRequestBehavior.AllowGet);
}
}
}
Model
class JSONResponse{
public int Value { get; set; }
public string Text { get; set; }
}
I'm calling an wcf restful service asynchronously from an asp.net mvc application and displaying the result in a div.
When I click the button and the service starts processing and I try to change page meanwhile, I can't... and the page only changes after I get the result from the service.
How can I make it so I can keep changing while the service is executing and when is finished I just display the data in the div?
EDIT: Changing page meaning render different partial views below the div.
As I describe on my blog, async doesn't change the HTTP protocol.
You'll need to use a technology designed for this, such as SignalR.
I am building a MVC3 web application and I am using knockoutjs. There are two views in the application. SetUpNewCompany and ManageAccount. To Set up a new company the user first enters the account number and clicks search. If the account number already exists the user can click on a button to go to the ManageAccount view. In the SetUpNewCompanyController I redirect using the RedirectToAction method. However, when the Index2 action in ManageAccount is executed the view is not displayed. If I type in the complete URL the view is displayed.
SetUpNewCompanyController.cs
[HttpPost]
public RedirectToRouteResult RedirectToManageAccount(string accountNumber)
{
return RedirectToAction("Index2", new RouteValueDictionary(new {controller=
"ManageAccount", companyId = "7e96b930-a786-44dd-8576-052ce608e38f" }));
}
This above is called by the function below when a button is clicked
self.redirectToManageAccount = function () {
var accountNumber = "7e96b930-a786-44dd-8576-052ce608e38f";
$.ajax({
type: "POST",
url: "/SetUpNewCompany/RedirectToManageAccount",
data: { accountNumber: accountNumber },
success: function (data) {
},
error: function () {
}
});
}
ManageAccountController.cs
public ActionResult Index2(String companyId)
{
var viewModel = new Models.Index();
List<String> compList = new List<String>();
compList.Add("MyCompany");
List<String> usersList = new List<String>();
usersList.Add("User1");
viewModel.Users = usersList;
viewModel.Companies = compList;
viewModel.CompanyId = companyId;
viewModel.Role = "Role1";
return View("ManageAccount",viewModel);
}
The URL that is generated is
http://localhost:53897/ManageAccount/Index2?companyId=7e96b930-a786-44dd-8576-
052ce608e38f
The console window in Firebug shows
GET http://localhost:53897/ManageAccount/Index2?companyId=7e96b930-a786-44dd-8576-
052ce608e38f 200 OK and the spinner keeps spinng
Also, how do I get the URL below instead of the one with querystring
http://localhost:53897/ManageAccount/Index2/7e96b930-a786-44dd-8576-052ce608e38f
Since you use AJAX to call the RedirectToManageAccount action method, you are responsible for handling its response yourself and as your success handler function is empty, you are effectively ignoring whatever arrives as a response.
If you want to force a redirect from within the AJAX response handler, I suggest
Modifying your action method as follows
[HttpPost]
public ActionResult RedirectToManageAccount(string accountNumber)
{
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index2", "ManageAccount", new { companyId = "7e96b930-a786-44dd-8576-052ce608e38f" });
return Json(new { Url = redirectUrl });
}
Updating your AJAX call in this way
self.redirectToManageAccount = function () {
var accountNumber = "7e96b930-a786-44dd-8576-052ce608e38f";
$.ajax({ type: "POST",
url: "/SetUpNewCompany/RedirectToManageAccount",
data: { accountNumber: accountNumber },
dataType: 'json',
success: function (response) {
window.location.href = response.Url;
},
error: function () {
}
});
}
As for your second question:
Also, how do I get the URL below instead of the one with querystring
http://localhost:53897/ManageAccount/Index2/7e96b930-a786-44dd-8576-052ce608e38f
You just have to define an appropriate route entry for this URL in your RegisterRoutes() function:
routes.MapRoute(null,
"ManageAccount/Index2/{companyId}",
new { controller = "ManageAccount",
action = "Index2" }
);
EDIT: As your AJAX call only serves to call an action method which causes a redirect, you can simplify it in a following way, provided you in this point (on the client side) know the companyId already:
self.redirectToManageAccount = function () {
var companyId = "12345";
window.location.href = '#(Html.ActionUri("Index2", "ManageAccount"))?companyId=' + companyId;
}
where I used this extension method
public static string ActionUri(this HtmlHelper html, string action, string controller)
{
return new UrlHelper(html.ViewContext.RequestContext).Action(action, controller);
}
I add a link dynamically to a page, and I want the "name" property to be a value that is sent back from server.
This is the code I have for adding a song to the server and then I dynamically append link to my song with a delete button, and I want that button to have a name equal to the songID evaluated on the server side.
$.ajax({
url: "/Home/AddSong",
type: "POST",
data: $("#AddTopTenFavForm").serialize(),
success: function () { ShowMsg("Song Added Successfully"), $(container).find('ul').append('<li><a class="topTenFavLinks" href="#" name="' + substr + '" >' + name + '</a> <span name= #item.SongId class="btnDeleteSong dontDoAnything">x</span></li>'); },
error: function () { ShowMsg("There was an error therefore song could not be added, please try again") }
});
here is my mvc action:
[HttpPost]
public ActionResult AddSong(HomeViewModel songModel)
{
var song = new Song();
song.GenreId = songModel.topTenFav.Rank;
song.Date = DateTime.Now;
song.UserName = User.Identity.Name;
song.Title = songModel.topTenFav.Title;
song.YoutubeLink = songModel.topTenFav.YoutubeLink;
repository.AddSong(song);
repository.Save();
return RedirectToAction("Index");
}
How would I solve this issue in a single ajax request?
You need to return your song ID from the action
[HttpPost]
public ActionResult AddSong(HomeViewModel songModel)
{
//code goes here
return this.Content(song.Id.ToString());
}
and in the javascript success callback you will receive data in arguments:
success: function (data) { /* use data here for anchor name */ },
Use JsonResult to return your Id, and append to your link.
Look at examples
http://shashankshetty.wordpress.com/2009/03/04/using-jsonresult-with-jquery-in-aspnet-mvc/
http://geekswithblogs.net/michelotti/archive/2008/06/28/mvc-json---jsonresult-and-jquery.aspx