Get Selected Item from dropdown and pass it to an onClick event - asp.net-core-mvc

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)
{
...
}

Related

How to make an ajax call to controller action

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);
}

Data from ajax post is passing null to the controller

AJAX call -
Here countryId is passed as "AU" for example -
$("#Countries").change(function () {
var countryId = this.value;
$.ajax({
url: '/Registers/GetStates',
type: "POST",
data: { 'data': countryId },
success: function (states) {
$("#States").html(""); // clear before appending new list
$.each(states, function (i, state) {
$("#States").append(
$('<option></option>').val(state.Id).html(state.Name));
});
}
});
});
After calling the GetStates method 'countryId' is always passed as null in the controller method. Not sure what I'm missing here.
I tried JSON.Stringify({ 'data': countryId }) also. Can anyone help me out ?
Controller Action -
[HttpPost]
public SelectList GetStates(string countryId)
{
return Helper.GetStates(countryId);
}
The parameter in your action method should be exactly same as the parameter name in the 'data' option of ajax.
In your case it is 'countryId'
[HttpPost]
public SelectList GetStates(string countryId)
{
return Helper.GetStates(countryId);
}
Change your ajax data option accordingly.
data: { countryId: countryId },
It will work.

When I ajax post json data but also received null

I try so many times to do below these code . but it still recive the value is null.
var cartViewModel = [];
$(":text").each(function (i) {
var quantity = parseInt($(this).val());
var id = parseInt($(this).data("id"));
cartViewModel.push({ id: id, quantity: quantity });
}
and next I use $.post to submit cartViewModel
the code such like:
var data= { data: JSON.stringify(cartViewModel) };
$.post(url,data,function(json){
//....
});
public class ShoppingCartViewModel
{
public int Id { get; set; }
public int Quantity { get; set; }
}
[HttpPost]
public ActionResult SubmitCart(List<ShoppingCartViewModel> models)
{
return Json(result);
}
but the arg 'models' also is null, I feel very confused. who can point out the right way. thx!
The model binder is expecting a property named models, but you're using the name data. What happens if you change
var data= { data: JSON.stringify(cartViewModel) };
to
var data= { models: JSON.stringify(cartViewModel) };
Edit:
The reason your models property is now empty is because you're calling JSON.stringify(cartViewModel). Instead of passing the action an array of objects, your passing it a string (that happens to be a representation of an array of objects).
Change your data definition to:
var data = { models: cartViewModel };
Edit again:
The above works fine for MVC5. It does not work in MVC4. To make it work in MVC4:
$.ajax({
type: 'POST',
url: '#Url.Action("Add", "Home")',
data: JSON.stringify({ models: cartViewModel }),
contentType: 'application/json',
});

MVC RedirectToAction through ajax jQuery call in knockoutjs is not working

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);
}

Returning data from server asp.net mvc action to Jquery Ajax request

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

Resources