using select options to get value in asp.net razor page - asp.net-core

I want to create a select option to input one of a few fixed values and have it return a matching value to a variable similar to how the input text fields, how would I do this? This was my attempt, the <input type="text"> works fine but the select types return null.
<div class="text-center">
<h1 class="display-4">Add new patient</h1>
<form method="post">
<input type="text" asp-for="patientModel.PatientID" placeholder="Patient ID" />
<input type="text" asp-for="patientModel.FirstName" placeholder="First Name" />
<input type="text" asp-for="patientModel.SecondName" placeholder="Second Name" />
<input type="text" asp-for="patientModel.Location" placeholder="Location" />
<select id="active" name="active" asp-for="patientModel.Sex">
<option value="ACTIVE">MALE</option>
<option value="INACTIVE">FEMALE</option>
<option value="OTHER">OTHER</option>
</select>
<select id="active" name="active" asp-for="patientModel.Active">
<option value="ACTIVE">ACTIVE</option>
<option value="INACTIVE">INACTIVE</option>
</select>
<button type="submit">Submit</button>
</form>
</div>
public class addnewpatientModel : PageModel
{
[BindProperty]
public PatientModel patientModel { get; set; }
public void OnGet()
{
}
public IActionResult OnPost()
{
return RedirectToPage("/index");
}
}

Change the name attribute for the select tag or just remove it:
<select id="sex" name="patientModel.Sex" asp-for="patientModel.Sex">
<select id="active" name="patientModel.Active" asp-for="patientModel.Active">

Try this link. I think you'll find an answer here
The select element has a name attribute. This is used as the key for any selected value(s) when a form is submitted. You can access the value by passing the key as an indexer to the Request.
var value = Request.Form["active"];
The recommended approach, however is to add a suitable property to the PageModel and to allow model binding to apply the posted value to the property:
public class addnewpatientModel : PageModel
{
[BindProperty]
public int active { get; set; }
public void OnPost()
{
// posted value is assigned to the Number property automatically
}
}

Related

Changing attributes of HTML element in server-side code in Razor Pages

I want to be able to access and modify attributes of HTML elements of a page in my server side code (I am using ASP.NET Core Razor Pages 6.0).
For example: a .cshtml file, I have a simple element like this:
<div class="mb-3 mt-3">
<label asp-for="User.firstname" class="form-label">First Name:</label>
<input asp-for="User.firstname" class="form-control" placeholder="First Name">
</div>
How do I access & change attributes of the above <input> element inside the OnGet or OnPost server-side methods?
I need to do so as I want to add a class to that <input> element, or make it read-only (depending on certain conditions in my server code).
In older versions of .NET, I believe this was possible by giving an HTML element an ID, and writing runat="server". Then, one could access the element in the code-behind via its ID and change its attributes. How is this done now in Razor Pages?
Should I not be able to do the same because of the asp-for tag helper which I used inn my code above? But how?
Thank you for your help!
you can achieve sending Value to the server with
This at razor page:
<form method="post">
<div class="form-group">
<input name="title" class="form-control" placeholder="Type title here.." />
<button type="submit" class="btn btn-primary">Post</button>
</form>
This at Model Page
public async Task<IActionResult> OnPostAsync(string title)
{
//do your stuff
}
Put breakpoint at public async Taks and viola.
I believe this should do the trick. You can change it for yourself.
Here is a whole working demo you could follow:
Model
public class User
{
public string firstname { get; set; }
}
Page(.cshtml file)
#page
#model IndexModel
<form method="post">
<div class="mb-3 mt-3">
<label asp-for="User.firstname" class="form-label">First Name:</label>
<input asp-for="User.firstname" class="form-control" placeholder="First Name">
</div>
<input type="submit" value="Post"/>
</form>
PageModel(.cshtml.cs file)
1.For model binding of the element, one way is that you can use [BindProperty]:
public class IndexModel : PageModel
{
[BindProperty]
public User User { get; set; }
public void OnGet()
{
}
public void OnPost()
{
//do your stuff.....
}
}
2.The second way is that you can add parameters like below:
public class IndexModel : PageModel
{
public User User { get; set; }
public void OnGet()
{
}
public void OnPost(User User)
{
}
}

model property is not passed to controller action

What is my mistake? AllFindedBrands property is not passing to SearchBrandResult Action of Controller
Controller:
public async Task<IActionResult> Search(string Articul, int idClient)
{
List<BrandList> findedBrands = new List<BrandList>();
#ViewBag.list = woDupes;
SearchViewModel model = new SearchViewModel();
model.Articul = Articul;
model.idClient = idClient;
model.AllFindedBrands = new List<BrandList>(findedBrands);
return View(model);
}
[HttpPost]
public async Task<IActionResult> SearchBrandResult(SearchViewModel model)
{
return View();
}
View:
<form asp-controller="Search" asp-action="SearchBrandResult" asp-route-
Articul="#Model.Articul"
asp-route-AllFindedBrands="#Model.AllFindedBrands" asp-route-
idClient="#Model.idClient" method="post" enctype="multipart/form-data">
<select asp-for="SelectedBrand" asp-items="#(new SelectList(#ViewBag.list,
nameof(FindedBrand.Name),
nameof(FindedBrand.Name)))"
multiple="true" class="form-control brand-chosen">
</select>
<input type="submit" />
All other properties of ViewModel is successfully passed to th Action
AllFindedBrands is type of complex model and asp-route-* cannot dynamic bind the value. You can F12 in the browser to check the generated url in the form.
Two ways you can follow:
1.By using asp-all-route-data and foreach the AllFindedBrands to bind the value which passes the value by route data.
Assume your model like below:
public class SearchViewModel
{
public string Articul { get; set; }
public string idClient { get; set; }
public List<BrandList> AllFindedBrands { get; set; }
public List<string> SelectedBrand { get; set; }
}
public class BrandList
{
public string Name { get; set; }
}
View(For easy testing, I just hard-coded the dropdownlist):
#model SearchViewModel
#{
var data = new Dictionary<string, string>();
for(int i=0;i<Model.AllFindedBrands.Count();i++)
{
data.Add("AllFindedBrands[" + i + "].Name", Model.AllFindedBrands[i].Name);
}
}
<form asp-action="SearchBrandResult" asp-route-Articul="#Model.Articul" asp-all-route-data="#data" asp-route-idClient="#Model.idClient" method="post" enctype="multipart/form-data">
<select asp-for="SelectedBrand" multiple="true" class="form-control brand-chosen">
<option value="aaa">aaa</option>
<option value="bbb">bbb</option>
<option value="ccc">ccc</option>
</select>
<input type="submit" />
</form>
2.By listing the property and make them hidden inputs which passes the value by form data:
#model SearchViewModel
<form asp-action="SearchBrandResult" asp-route-Articul="#Model.Articul" asp-route-idClient="#Model.idClient" method="post" enctype="multipart/form-data">
#for (int i = 0; i < Model.AllFindedBrands.Count(); i++)
{
<input asp-for="#Model.AllFindedBrands[i].Name" hidden />
}
<select asp-for="SelectedBrand" multiple="true" class="form-control brand-chosen">
<option value="aaa">aaa</option>
<option value="bbb">bbb</option>
<option value="ccc">ccc</option>
</select>
<input type="submit" />
</form>

blazorstrap InputType.select not binding

trying to create a very basic form with blazorstrap.
#page "/testform"
<h1> test form #Status</h1>
<EditForm Model=#Person OnSubmit=#FormSubmitted>
<DataAnnotationsValidator />
<ValidationSummary />
<p>
<label>
name:
<BSBasicInput T="string"
InputType="InputType.Text"
#bind-value=Person.Name />
</label>
</p>
<p>
<label>
Age:
<InputNumber #bind-Value="Person.Age" />
</label>
</p>
<p>
<label>
type:
<InputSelect #bind-Value="Person.Type">
<option value="">Select classification ...</option>
#foreach (var enumType in Enum.GetValues(typeof(BankAccountType)))
{
<option value="#enumType">#enumType</option>
}
</InputSelect>
#* <BSBasicInput T="BankAccountType?" InputType="InputType.Select" #bind-Value="Person.Type"> *#
#* <option value="">Select classification ...</option> *#
#* #foreach (var enumType in Enum.GetValues(typeof(BankAccountType))) *#
#* { *#
#* <option value="#enumType">#enumType</option> *#
#* } *#
#* </BSBasicInput> *#
</label>
</p>
<input type="submit" value="Submit" class="btn btn-primary" />
</EditForm>
#code
{
string Status = "Not submitted";
Person Person = new Person();
BankAccountType? AccountType = null;
void FormSubmitted()
{
Status = "Form submitted";
Console.WriteLine($"person: {Person} + " + AccountType);
}
private void SelectedChanged(BankAccountType? value)
{
Console.WriteLine("changed " + value);
}
}
the person class is
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public BankAccountType? Type { get; set; }
public override string ToString()
{
var accountType = Type.HasValue ? Type.Value.ToString() : "";
return $"{Name} is {Age} years old {accountType}";
}
}
The name binding with BSBasicInput works fine. using InputSelect for the select works fine. but when I try and use BSBasicInput with the InputType.Select (see commented out part). I cannot get it to bind, or at least show it is ever changing or setting either Person.Type or when I directly create a property in the razor file for it.
Sure I must be doing something wrong here, and its not blazorstrap, but can't see what it is now
<BSBasicInput T="BankAccountType" InputType="InputType.Select" #bind-Value="Person.Type">
<option value="">Select classification ...</option>
#foreach (var enumType in Enum.GetValues(typeof(BankAccountType)))
{
<option value="#enumType">#enumType</option>
}
</BSBasicInput>
This works. It seems to be that BSBasicInput cannot handle nullable enums

How do I route a variable to another page from a select list in Razor Pages

This likely has a simple solution but I've struggled for a while now.
I have a form with a select list, and I want to select an item and then send that item value to a new page using a button in the same form. For some reason I can't figure out how to save the item value, I don't know what I'm missing.
Page 1 html
<form method="post" class="container">
<h4>Generate printable list by lab</h4>
<div class="form-group form-row">
<select asp-for="LabNumberToFilter" asp-items="Model.LabNumberListOptions" class="form-control col-md-2">
<option value="">Select a lab number</option>
</select>
<span asp-validation-for="LabNumberToFilter" class="text-danger"></span>
<a class="btn btn-info btn-lg col-md-2" asp-page="./Page2"
asp-route-labNumber="#Model.LabNumberToFilter" />Create List<a/>
</div>
</form>
Page 1 model
[BindProperty]
public int LabNumberToFilter { get; set; }
public SelectList LabNumberListOptions { get; set; }
public async Task<IActionResult> OnGetAsync() {
(…)
LabNumberListOptions = new SelectList(_context.LabTours, nameof(LabTour.LabNumber), nameof(LabTour.LabNumber));
return Page();
}
Page 2 html
#page "{labNumber:int?}"
(…)
Page 2 model
public int LabNumber { get; set; }
public IList<LabTour> LabTourList { get; set; }
public async Task OnGetAsync(int? labNumber)
{
LabNumber = labNumber.Value;
LabTourList = await _context.LabTours.Where(l => l.LabNumber == LabNumber).ToListAsync();
}
If I put a default value in for my LabNumberToFilter, the button routes the default value correctly, so the problem is that my select list doesn't save/use the new inputted value when I hit the button to redirect to page 2. What did I do wrong?
Specify an action in the form that points to page 2. You can do this either by explicitly setting the action attribute:
<form method="post" action="/Page2">
or by passing the page name to the asp=page attribute:
<form method="post" asp-page="/Page2">
Then in Page2, add the [BindProperty] attribute to a public property with the same name as the parameter specified by the asp-for attribute in the select element (LabNumberToFilter):
[BindProperty]
public int LabNumberToFilter { get; set; }
This will capture the posted value. You don't need the parameter in the handler method, or the route template.
Note that the form's method is Post, so the OnGet handler in page 2 will not execute.
See here for more background on model binding in Razor Pages: https://www.learnrazorpages.com/razor-pages/model-binding
I would suggest using a datalist
You will have to load it in a loop but then you can access the value from the input e.g.
<form method="post">
<input type="text" asp-for="LabNumberToFilter" list="labNumbers" placeholder="Select or enter a lab number"/>
<datalist id="labNumbers">
#foreach (var labNum in Model.LabNumberListOptions)
{
<option value="#labNum"></option>
}
</datalist>
<button type="submit" ...
</form>

Trouble with Request.Form inside .cshtml

Trying to create a page that will have a drop down selector with three image names and when an image name is selected and you hit submit it will then display that image on the page.
I found an example of this here(Seems to be outdated): https://learn.microsoft.com/en-us/aspnet/web-pages/overview/ui-layouts-and-themes/9-working-with-images
has: if(Request["photoChoice"] != null)
Read somewhere that the correction is Request.Form
#{ var imagePath = "";
if (Request.Form["photoChoice"] != null)
{
imagePath = #"images\" + Request.Form["photoChoice"];
}
}
<form method="post" action="">
<div>
I want to see:
<select name="photoChoice">
<option value="Photo1.jpg">Photo 1</option>
<option value="Photo2.jpg">Photo 2</option>
<option value="Photo3.jpg">Photo 3</option>
</select>
<input type="submit" value="Submit" />
</div>
<div style="padding:10px;">
#if (imagePath != "")
{
<img src="#imagePath" alt="Sample Image" width="300" />
}
</div>
</form>
The first error I was having was:
" Operator '!=' is ambiguous on operands of type 'StringValues' and 'null' "
adding (object) at the start of the Request there in the if statement
#{ var imagePath = "";
if ((object)Request.Form["photoChoice"] != null)
{
imagePath = #"images\" + Request.Form["photoChoice"];
}
Now I am getting another error "InvalidOperationException: Incorrect Content-Type" when I try to compile the site. It does refer to the If line of code
The link you refer to is used in asp.net, not in core.
The main reason for the error is that you put the request.Form in the
wrong place. Your current requirements should put the code
into the OnPost method in the code behind.
There are many ways to implement this function in the core, but they need to be triggered in the post method in the code behind.
Please refer to this.
The simplest way is to bind fields in the code behind. Please refer to the following for details.
Page.cs:
public class ShowImagesModel : PageModel
{
[BindProperty]
public string imagePath { get; set; }
[BindProperty]
public string photoChoice { get; set; }
public void OnGet()
{
imagePath = "";
}
public void OnPost()
{
if (!string.IsNullOrEmpty(photoChoice))
{
imagePath = #"images\" + photoChoice;
}
}
}
View:
#page
#model WebApplication1_razor_page.ShowImagesModel
#{
ViewData["Title"] = "ShowImages";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<h1>ShowImages</h1>
<form method="post" action="">
<div>
I want to see:
<select asp-for="photoChoice" >
<option value="Photo1.jpg">Photo 1</option>
<option value="Photo2.jpg">Photo 2</option>
<option value="Photo3.jpg">Photo 3</option>
</select>
<input type="submit" value="Submit" />
</div>
<div style="padding:10px;">
#if (Model.imagePath != "")
{
<img src="#Model.imagePath" alt="Sample Image" width="300" />
}
</div>
</form>
Here is the result: