How to pass HTML selected value to controller - asp.net

I am trying to pass the value from my HTML select to a controller, but I am not sure why the method is not capturing the values in spite of the select id has the same name than model.
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CountryId,ProvinceId,CityId")] ads_post ads_post)
{
var currUser = currentUser.GetCurrUser();
ads_post.UserId = currUser.Id;
ads_post.PostDate = DateTime.Now;
ads_post.SponsoredType = null;
ads_post.PriorityType = null;
if (ModelState.IsValid)
{
db.ads_post.Add(ads_post);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.PriorityType = new SelectList(db.ads_priority_plan, "Id", "Name");
ViewBag.SponsoredType = new SelectList(db.ads_sponsored_plan, "Id", "Name");
ViewBag.CurrencyType = new SelectList(db.ads_currency, "Id", "Name");
return View(ads_post);
}
This is the HTML
<div class="row mb-3 mt-5">
<div class="col-md-4">
<label><strong>País donde quieres publicar:</strong> <i class="fas fa-list-ul"></i></label>
<select id="CountryId" onchange="getProvices();"></select>
</div>
<div class="col-md-4">
<label><strong>Provincia:</strong> <i class="fas fa-list-ul"></i></label>
<select id="ProvinceId" onchange="getCities();"></select>
</div>
<div class="col-md-4">
<label><strong>Ciudad:</strong> <i class="fas fa-list-ul"></i></label>
<select id="CityId"></select>
</div>
</div>
Can somebody help me out with this?
Thank in advance.

I found by myself, I had just to add a name attribute to the HTML and that's it.

Related

asp.net core - form values return null

Passing department and title models for use data in selectbox and passing employee model for save data from user. tring to pass values from partial view but in controller values return null.
partial view:
#model (List<Department> Departments, List<Title> Titles, Employee e)
<form class="g-3" asp-action="CreateEmployee" asp-controller="Employees" method="post">
<div class="row">
<div class="col-lg-6">
<div class="mb-3">
<label for="Name" class="form-label">İsim</label>
<input asp-for="e.Name" type="text" class="form-control" id="Name">
<div class="invalid-feedback">
İsim alanı boş bırakılamaz.
</div>
</div>
</div>
</div>
<button type="submit">Tek Form</button>
</form>
controller:
public IActionResult CreateEmployee()
{
HR_ManagementContext context = new HR_ManagementContext();
var departments = context.Departments.ToList();
var titles = context.Titles.ToList();
var models = (departments, titles, new Employee());
return View(models);
}
[HttpPost]
public IActionResult CreateEmployee(Employee employee)
{
return RedirectToAction("CreateEmployee");
}
Set the name attribute in the input tag:
<input asp-for="e.Name" type="text" class="form-control" id="Name", name="employee.Name">
The second solution is to use model name item3 generated by the MVC:
[HttpPost]
public IActionResult CreateEmployee(Employee item3)
{
return RedirectToAction("CreateEmployee");
}
Thx #Jackdaw his answer also working too.
I found an alternative
in Controller you can bind model:
public IActionResult CreateEmployee([Bind(Prefix = "Item3")]Employee employee)
{
return RedirectToAction("CreateEmployee");
}
Item3 is the prefix of tuple model.
#model (List<Department> Departments, List<Title> Titles, Employee e)
Department = Item1
Titles = Item2
Employee = Item3

How to make a prepopulated form in ASP.NET MVC and Entity Framework

So I have a list of clients in a database with various information about them. I need to print all of them out with a slidedown form with their current information already there, and the ability to add or change it.
I am able to print out all the clients and their info but when I try to edit the form it is disabled even though there is no disabled attribute set.
Here is the controller
public ActionResult Index()
{
var context = new U2XPlanningAutomationToolEntities();
string query = "SELECT * FROM Clients";
IEnumerable<Client> data = context.Database.SqlQuery<Client>(query);
List<Client> clients = new List<Client>(data);
ViewBag.Clients = clients;
string email = Session["email"] as string;
if (!String.IsNullOrEmpty(email))
{
return View();
}
return View("../Account/Login");
}
The View
#foreach (var client in ViewBag.Clients)
{
string plan_changes = client.plan_changes;
string critical_milestones = client.critical_milestones;
string pdd = client.pdd;
string inbound = client.inbound;
string outbound = client.outbound;
string other = client.other;
<div class="row client">
<div class="col-sm-3"><span id="#client.id" class="glyphicon glyphicon-plus dropdownBtn"></span><p>#client.name</p></div>
<div class="col-sm-3"><p>#client.oep_start</p></div>
<div class="col-sm-3"><p>#client.oep_end</p></div>
<div class="col-sm-3 text-right"><button id="#client.id" class="btn btn-primary delete-client">Delete</button></div>
<div class="col-sm-12 slider" id="slider_#client.id">
#using (Html.BeginForm("UpdateClient", "Home", FormMethod.Post))
{
<div class="col-sm-4">
<input type="hidden" name="id" value="#client.id" />
#Html.LabelFor(c => c.plan_changes, "Plan Changes")
#*<textarea name="plan_changes" class="form-control" cols="20" rows="2">#plan_changes</textarea>*#
#Html.TextArea("plan_changes", plan_changes, new { #class = "form-control" })
#Html.LabelFor(c => c.critical_milestones, "Critical Milestones")
#Html.TextArea("critical_milestones", critical_milestones, new { #class = "form-control" })
</div>
<div class="col-sm-4">
#Html.LabelFor(c => c.pdd, "Plan Document Design")
#Html.TextArea("pdd", pdd, new { #class = "form-control" })
#Html.LabelFor(c => c.inbound, "Inbound")
#Html.TextArea("inbound", inbound, new { #class = "form-control" })
</div>
<div class="col-sm-4">
#Html.LabelFor(c => c.outbound, "Outbound")
#Html.TextArea("outbound", outbound, new { #class = "form-control" })
#Html.LabelFor(c => c.other, "Other")
#Html.TextArea("other", other, new { #class = "form-control" })
</div>
<div class="col-sm-12 text-center">
<input type="submit" value="Update" name="update" class="btn btn-primary" />
</div>
}
</div>
</div>
}
If my approach seems weird to you it might be because I am brand new to MVC ASP.NET, I am coming from a PHP background.
Thanks in advance!
Please use a IEnumerable<Client> in you view instead of putting it into a viewbag. Can you try to pass the id in the Html.BeginForm. Do you have an UpdateClient method in your HomeController class?

How to redirect a ASP.NET Core MVC partial view after file download

I have an asp.net core MVC partial view called ExportPagePartial that allows user to export a page from the system and downloads it. In the HttpGet controller action I show the partial view (as a Modal pop-up) to get user input.
Modal Popup
<a class="dropdown-item" asp-action="ExportPagePartial" asp-route-userId="#Model.UserId" asp-route-businessAccountId="#Model.BusinessAccountId" asp-route-projectId="#Model.ProjectId" asp-route-pageId="#Model.PageId" data-toggle="modal" data-target="#ModalPlaceholder" title="Export page."><i class="fas fa-cloud-download-alt"></i> Export</a>
Controller Get Action
[HttpGet]
public IActionResult ExportPagePartial(string userId, string businessAccountId, string projectId, string pageId)
{
ExportPageViewModel model = new ExportPageViewModel()
{
// Set properties
};
return PartialView(nameof(ExportPagePartial), model);
}
Once the user hits Export button from the Modal pop-up partial view (which is a form submit action) the following HTTPPost action is correctly called.
In this action I have to get the file from the Web Api and then download it via the browser, however after download is complete i want to close the partial view. Once the download is complete the partial view is still visible.
The return action never works and partial modal pop-up view does not close
return RedirectToAction(nameof(BlahRedirectAction));
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExportPagePartial(ExportPageViewModel model)
{
// Call Web API to get the file
string downloadUrl = "blah_blah_url";
using (HttpResponseMessage httpResponse = await WebApiClient.HttpClient.PostAsJsonAsync(downloadUrl, unprotectedExportInput))
{
if (!httpResponse.IsSuccessStatusCode)
{
throw new InvalidOperationException(await httpResponse.Content.ReadAsStringAsync());
}
// Download the file now.
ActionContext actionContext = new ActionContext(HttpContext, ControllerContext.RouteData, ControllerContext.ActionDescriptor, ModelState);
FileStreamResult fileContent = File(await httpResponse.Content.ReadAsStreamAsync(), httpResponse.Content.Headers.ContentType.MediaType, httpResponse.Content.Headers.ContentDisposition.FileName);
await fileContent.ExecuteResultAsync(actionContext);
}
// Redirect to main pain
// The view never redirects and partial view is still visible
return RedirectToAction(nameof(BlahRedirectAction));
}
fileContent.ExecuteResultAsync(actionContext);
This is because when you download the file, ExportPagePartial has determined the return flow, and will not perform the RedirectToAction.
I suggest that you change the post method that triggers ExportPagePartial to ajax to achieve, so that you can successfully execute ExportPagePartial and after the method, redirect the page to what you want in js.
Here is a complete code of my demo based on your code:
public class ExportTestController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult ExportPagePartial(string userId, string businessAccountId, string projectId, string pageId)
{
ExportPageViewModel model = new ExportPageViewModel()
{
Id = 1,
Gender = "male",
Name = "aaa",
Number = "1231244"
};
return PartialView(nameof(ExportPagePartial), model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExportPagePartial(ExportPageViewModel model)
{
// Call Web API to get the file
string downloadUrl = "blah_blah_url";
using (HttpResponseMessage httpResponse = await WebApiClient.HttpClient.PostAsJsonAsync(downloadUrl, unprotectedExportInput))
{
if (!httpResponse.IsSuccessStatusCode)
{
throw new InvalidOperationException(await httpResponse.Content.ReadAsStringAsync());
}
// Download the file now.
ActionContext actionContext = new ActionContext(HttpContext, ControllerContext.RouteData, ControllerContext.ActionDescriptor, ModelState);
FileStreamResult fileContent = File(await httpResponse.Content.ReadAsStreamAsync(), httpResponse.Content.Headers.ContentType.MediaType, httpResponse.Content.Headers.ContentDisposition.FileName);
await fileContent.ExecuteResultAsync(actionContext);
}
// Redirect to main pain
// The view never redirects and partial view is still visible
return RedirectToAction(nameof(BlahRedirectAction));
}
Index.cshtml:
#{
ViewData["Title"] = "Index";
Layout = null;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script>
$(function () {
$("a").click(function () {
var route = $(this).attr("href");
$('#partial').load(route);
})
$("form").submit(function () {
$.ajax({
url: $("form").attr('action'),
type: 'Post',
data: $("form").serializeArray(),
success: function () {
//$("#ModalPlaceholder").hide();
window.location.href = "/ExportTest/BlahRedirectAction";
}
});
})
})
</script>
<a class="dropdown-item" asp-action="ExportPagePartial"
asp-route-userId="1" asp-route-businessAccountId="1"
asp-route-projectId="1" asp-route-pageId="1"
data-toggle="modal" data-target="#ModalPlaceholder" title="Export page."><i class="fas fa-cloud-download-alt"></i> Export</a>
<div class="modal fade" id="ModalPlaceholder" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<form asp-action="ExportPagePartial" method="post">
<div id="partial">
</div>
</form>
</div>
ExportPagePartial.cshtml:
#model ExportPageViewModel
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label asp-for="Id" class="control-label">#Model.Id</label>
<input asp-for="Id" class="form-control" hidden />
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Gender" class="control-label"></label>
<input asp-for="Gender" class="form-control" />
<span asp-validation-for="Gender" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Number" class="control-label"></label>
<input asp-for="Number" class="form-control" />
<span asp-validation-for="Number" class="text-danger"></span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" >Save changes</button>
</div>
</div>
</div>
Here is the test result:

Selecting user with asp.net mvc

I have a list of users and if you click on a user there has to be create a new message.
But every time I click on a user id is 0
I have this:
action method:
public ActionResult StuurBericht(int id = 0, string onderwerp = "")
{
using (var rep = new GebruikerRepository(Context.Klant.Id))
{
var model = PersoneelsDossierService.GetPersoneelsDossierMutatieModel(Context.Klant.Id, GetMutatieRol(), int.Parse(Context.Gebruiker.ExternId), Gebruiker.DienstverbandId, Gebruiker.DienstverbandId, "Functionarissen");
model.Functionarissen = PersoneelsDossierService.GetFunctionarissen(Context.Klant.Id, Gebruiker.DienstverbandId);
BeveiligingService.ControleerGebruikerVanKlant(Context.Klant.Id, Context.Gebruiker.Id);
if (id > 0)
{
ModelState.Clear();
var modelMessage = new Message();
modelMessage.GebruikerId = id;
modelMessage.Onderwerp = string.Format("RE: {0}", onderwerp);
return View(model);
}
}
return View();
}
and this is the view:
#model List<SDB.Models.Stamtabel>
#{
var ItemsByAccordatieFunctieGroep = Model.GroupBy(a => a.Code);
<div class="row">
#foreach (var Accordeerders in ItemsByAccordatieFunctieGroep)
{
<div class="col-md-4">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading blue">#Accordeerders.Key</div>
<!-- List group -->
<ul class="list-group">
#foreach (var Accordeerder in Accordeerders)
{
<li class="list-group-item">
#Accordeerder.Omschrijving
</li>
}
</ul>
</div>
</div>
}
</div>
}
So my question is:
How to return the correct user and that you will get the correct id?
Thank you
this has to be the link for new message:
SelfService/Profiel/Nieuw?id=6240&onderwerp=test
So the controller is: Profiel.
But now the link is this:
/PersoneelsDossier/StuurBericht/0?onderwerp=HRM%20Management
So the controller link is incorrect.
Your #Url.Action is wrong, it should be:
#Accordeerder.Omschrijving

How to change custom columns in AspNetUsers table

I'm very new to ASP.NET, but I've added a FirstName (string), LastName (string), and AccountType (int, which can be a 0, 1, or 2) to my AspNetUsers database. I am working in MVC 5. While I've found numerous articles about changing the password, but I'd like to add the ability to let users change AccountType.
I am aware that the Roles might have been a better option in this case, but I've implemented so much already I'd rather not change that now.
The form for the Account Type Change contains a field for the user to input his/her password (to confirm that they would like the Account Type changed, and a dropdown list giving three options whose value is either 0, 1, or 2.
In short, the user will enter their password, click an option on the dropdownlist, then click the "sumbit button" and AccountType will be changed to a different int
#using SouthMeckNTHS.Models
#using SouthMeckNTHS.Extensions
#model ChangeAccountViewModel
#{
ViewBag.Title = "Change Account Type";
}
<section class="engine"></section>
<section class="mbr-section article mbr-parallax-background mbr-after-navbar" id="msg-box8-7d" style="background-image: url(../assets/images/full-unsplash-photo-1438354886727-070458b3b5cf-2000x1553-39.jpg); padding-top: 120px; padding-bottom: 80px;">
<div class="mbr-overlay" style="opacity: 0.5; background-color: rgb(34, 34, 34);">
</div>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 text-xs-center">
<h3 class="mbr-section-title display-2">MANAGE YOUR ACCOUNT</h3>
<div class="lead"><p>Change your account settings</p></div>
</div>
</div>
</div>
#using (Html.BeginForm("AccountChange", "Manage", FormMethod.Post, new {
#class = "form-horizontal", role = "form" }))
{
Html.AntiForgeryToken();
<div class="mbr-section mbr-section__container mbr-section__container--middle">
<div class="container">
<div class="row">
<div class="col-xs-12 text-xs-center">
</div>
</div>
</div>
</div>
<div class="mbr-section mbr-section-nopadding">
<div class="container">
<div class="row">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="col-xs-12 col-lg-10 col-lg-offset-1">
<div class="row row-sm-offset">
<div class="col-xs-12 col-md-12">
<div class="form-group">
<label class="form-control-label" for="form1-z-name">Enter your current email<span class="form-asterisk">*</span></label>
#Html.TextBoxFor(m => m.CurrentPassword, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.CurrentPassword, "", new { #class = "text-danger", #style = "color:white" })
<!--<input type="text" class="form-control" name="name" required="" data-form-field="Name" id="form1-z-name">-->
</div>
</div>
<div class="col-xs-12 col-md-12">
<div class="form-group">
<label class="form-control-label" for="form1-z-name">Choose Your Account Type<span class="form-asterisk">*</span></label>
#Html.DropDownListFor(
m => m.NewAccountType,
new SelectList(
new List<Object>
{
new { value = 0 , text
= "Learner" },
new { value = 1 , text
= "Contributor" },
new { value = 2 , text
= "Competitor"}
},
"value",
"text"
), new { #style = "border: 1px solid #e8e8e8;padding: 0.5em 1.07em 0.5em;background: #f5f5f5;font-size: 0.875rem;border-radius: 5px;width: 100%;line-height: 1.43;min-height: 3.5em;" }
)
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="mbr-section mbr-section__container" id="buttons1-r" style="background-color: rgb(255, 255, 255); padding-top: 10px; padding-bottom: 5px;">
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="text-xs-center"><input type="submit" class="btn btn-primary text-xs-center" value="CHANGE ACCOUNT TYPE" /> </div>
</div>
</div>
</div>
</section>
}
And here is part of ManageViewModels.cs:
public class ChangeAccountViewModel
{
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string CurrentPassword { get; set; }
[Required]
[Display(Name = "Choose Account Type")]
public int NewAccountType { get; set; }
}
So, likely in ManageController.cs, what should I add to allow the information from the first part of the form to check against the user's password and what should I add to the same file so that (if the passwords match) it will update the AccountType database with the user's choice?
(An edited copy of the "change password" function did not work)
UPDATE
I added this to ManageController.cs:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AccountChange(ChangeAccountViewModel model)
{
if (ModelState.IsValid)
{
// Get the current application user
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
//Update the details
user.AccountType = model.NewAccountType;
// Update user address
var result = await UserManager.UpdateAsync(user);
}
return View(model);
}
But it only works once. I run a test of it, I change the user's account type, and it saves to the AspNetUsers db. However, when I run it again, I can't change it anymore in ANY user accounts. What should I do to get this to work every time the user changes the dropdownlist and clicks the submit button?
I decided to just log the user out and have them sign back in.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AccountChange(ChangeAccountViewModel model)
{
//THE THING THAT ONLY WORKED ONCE:
if (ModelState.IsValid)
{
// Get the current application user
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
//Update the details
user.AccountType = model.NewAccountType;
// Update user account type
var result = await UserManager.UpdateAsync(user);
if (result.Succeeded)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return RedirectToAction("../Account/Login");
}
}
return View(model);
}

Resources