.NET core MVC Make input element conditionally Readonly - c#

I am a new .NET programmer. I have the following input:
<input asp-for="FirstName"
id="FirstName"
class="form-control"
value="#Context.Request.Query["FirstName"]"
type="text"
readonly="readonly" />
If the textbox has data, I want the textbox to be readonly, if there is no data in the textbox, then the user can input data. Can anybody give advice?

If the textbox has data, I want the textbox to be readonly, if there
is no data in the textbox, then the user can input data. Can anybody
give advice?
According to your code and description, it seems that you want to set the textbox to be read-only based on the FirstName query string parameter. I suggest you could try to use the following code (use Razor syntax):
#model MVCDemo.Models.Customer
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName" class="control-label"></label>
#{
var value = Context.Request.Query["FirstName"].ToString();
if (string.IsNullOrEmpty(value))
{
<input asp-for="FirstName" id="FirstName" class="form-control" value="#value" type="text" />
}
else
{
<input asp-for="FirstName" id="FirstName" class="form-control" value="#value" type="text" readonly />
}
}
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
The screenshot as below:
Besides, if you want to make the textbox read-only after entering some value, you could use JQuery to add or remove the readonly attribute on the textbox.

You can do something like this
#{
var firstname= Context.Request.Query["FirstName"];
}
<input asp-for="FirstName" id="FirstName" class="form-control"
value="#Context.Request.Query["FirstName"]" type="text"
readonly="#(Context.Request.Query["FirstName"]=="" ? "False" : "True")">

Related

Create a Condition For all non empty fields to be ReandOnly - ASP.NET Core 6.0 MVC

I am developing my first web application with ASP.NET Core 6, and I have a form that shows some fields that I already have information inside of my database.
The problem is: these fields needs to be read-only, because my user needs to considerate the information from my database. If is null, then he needs to insert a value.
Here is an example (consider the field with already set readonly). Most of fields will need this code:
<div class="form-group row">
<div class="col-3">
<label for="Renda Bruta">Associado Desde:</label>
<input type="text" class="form-control">
</div>
<div class="col-3">
<label for="Renda Liquida">Cota Capital</label>
<input type="text" class="form-control">
</div>
<div class="col-6" style="text-align:center">
<label for="ServidorPublico">IAP:</label>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Quantidade" value="#Html.DisplayFor(model => model.iAP.QuantidadeProduto)" ReadOnly="readonly"/>
<input type="text" class="form-control" placeholder="Produtos" value=""#Html.DisplayFor(model => model.iAP.Pro)" ReadOnly="readonly"/>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label for="Renda Bruta">Margem Contribuição</label>
<input type="text" class="form-control">
</div>
<div class="col-8" style="text-align:center">
<label for="ServidorPublico">Cheque Especial</label>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Dias de Utilização" />
<input type="text" class="form-control" placeholder="Valor Utilizado" />
<input type="text" class="form-control" placeholder="Valor Contratado" />
</div>
</div>
</div>
I already build the form, and put some fields readonly with ReadOnly="readonly", but is there a way to loop all fields and put readonly with a loop or I really need to write in all fields the code `ReadOnly="readonly" ? My form is really big
But is there a way to loop all fields and put readonly with a loop or
I really need to write in all fields the code `ReadOnly="readonly" ?
My form is really big
Yes, you can set that ReadOnly attribute based on the value of your textbox field.
In this scenario you have to consider two way, either you should consider your textbox name attribute or type="text" attribute. Upon these two very way we will be decided which textbox set to readonly which is not.
For [type='text'] Attribute:
When [type='text'] means we will check all the textbox type of text and check if the textbox have value and set the readonly attribute:
View:
<div class="form-group row">
<div class="col-3">
<label for="Renda Bruta">Associado Desde:</label>
<input type="text" name="Associado" class="form-control">
</div>
<div class="col-3">
<label for="Renda Liquida">Cota Capital</label>
<input type="text" name="Cota" class="form-control">
</div>
<div class="col-6" style="text-align:center">
<label for="ServidorPublico">IAP:</label>
<div class="input-group mb-3">
<input type="text" name="Quantidade" class="form-control" placeholder="Quantidade" value="Test Value" />
<input type="text" name="Produtos" class="form-control" placeholder="Produtos" value="Test Value Products" />
</div>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label for="Renda Bruta">Margem Contribuição</label>
<input type="text" name="Margem" class="form-control">
</div>
<div class="col-8" style="text-align:center">
<label for="ServidorPublico">Cheque Especial</label>
<div class="input-group mb-3">
<input type="text" name="Dias" class="form-control" placeholder="Dias de Utilização" />
<input type="text" name="Utili" class="form-control" placeholder="Valor Utilizado" />
<input type="text" name="Contra" class="form-control" placeholder="Valor Contratado" />
</div>
</div>
</div>
Script:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$("input[type='text']").each(function (index, item) {
console.log(item);
if ($(item).val() != "") {
$(item).attr('readonly', true);
}
});
});
</script>
}
Note: When will will set readonly to a textbox which has value based on the text type then we have to consider like input[type='text']
For name Attribute:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$("input").each(function (index, item) {
console.log(item);
if ($(item).val() != "") {
$(item).attr('readonly', true);
}
});
});
</script>
}
Note: Remember in this scenario, you need to set name property for your textbox to identify uniquely as you can see I have added name property
Output:
what I understand that you want to make the input field enterable when the value of it is null. this is done by javascript.
I suggest to make all input fields read only.
use javascript to test each field, if its value is null make it enterable.
for example:
<input type="text" id="text1" class="form-control" placeholder="Quantidade" value="#Html.DisplayFor(model => model.iAP.QuantidadeProduto)" ReadOnly="readonly"/>
<script>
window.onload = function() {
if (document.getElementById("text1").value.length == 0)
{
document.getElementById("text1").readOnly = false;
}}
</script>
so basically when the page is loading the script will check if the input is null or not and it will do the action.

Binding generic value back to controller via post method

I can't figure out how to bind back generic value from view when sending it back to controller via post method.
I have generic class PageModel that inherites from GenericModel. PageModel has additional parameter Page (class that have two int parameters, pageSize and pageNumber). GenericModel has only generic value of T named viewModel and nothing more. The problem is that standard C# binder binds Page parameter without any issues, but no matter what I'm trying to do ViewModel is never filled in.
Models:
public class GenericModel<T>
{
public T ViewModel { get; set; }
public GenericModel(T viewModel)
{
ViewModel = viewModel;
}
public GenericModel()
{
}
}
public class PageModel<T> : GenericModel<T>
{
public Page Page { get; set; }
public PageModel(T viewModel, Page page) : base(viewModel)
{
Page = page;
}
public PageModel() : base()
{
}
}
Generic Parameter:
public class UserModel
{
public string Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public IList<string> Roles { get; set; }
public IList<string> NewRoles { get; set; }
}
Controller method
[HttpPost]
public async Task<IActionResult> Update(PageModel<UserModel> model)
{
var isUpdated = await _userServices.Update(model.ViewModel);
ViewData["IsUpdated"] = isUpdated;
return View("Index", await _userServices.GetUsersPage(model.Page.PageNumber, model.Page.PageSize));
}
View:
#model PageModel<UserModel>
#{
ViewData["Title"] = "Update";
}
<h1>Update</h1>
<form asp-controller="Admin" asp-action="Update" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="ViewModel.Id"></label>
<input type="text" asp-for="ViewModel.Id" disabled="disabled" class="form-control" />
<span asp-validation-for="ViewModel.Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ViewModel.Password"></label>
<input type="password" asp-for="ViewModel.Password" class="form-control" />
<span asp-validation-for="ViewModel.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ViewModel.ConfirmPassword"></label>
<input type="password" asp-for="ViewModel.ConfirmPassword" class="form-control" />
<span asp-validation-for="ViewModel.ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ViewModel.Roles"></label>
<input type="text" asp-for="ViewModel.Roles" class="form-control" hidden="hidden" />
<span asp-validation-for="ViewModel.Roles" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Page.PageNumber"></label>
<input type="number" asp-for="Page.PageNumber" class="form-control" hidden="hidden" />
<span asp-validation-for="Page.PageNumber" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Page.PageSize"></label>
<input type="number" asp-for="Page.PageSize" class="form-control" hidden="hidden" />
<span asp-validation-for="Page.PageSize" class="text-danger"></span>
</div>
#foreach (var availableRole in (IList<IdentityRole>)ViewData["AllRoles"])
{
<div class="form-check">
<input class="form-check-input" type="checkbox" name="newRoles" value="#availableRole.Name"
checked="#Model.ViewModel.Roles.Contains(availableRole.Name)">
<label class="form-check-label">#availableRole</label>
</div>
}
<button type="submit" class="btn btn-success">Change</button>
Do you know what can be the issue? Is naming convention wrong? I've already tried to find answer on stack, but with no luck.
**
EDIT 1:
**
This is what is generated by ASP.NET (Copied from google chrome)
<form method="post" action="/Admin/Update/439c61f5-d721-4e10-b49c-6263b7929c6a">
<div class="text-danger validation-summary-valid" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
<div class="form-group">
<label asp-for="ViewModel.Id"></label>
<input type="text" asp-for="ViewModel.Id" disabled="disabled" class="form-control" />
</div>
<div class="form-group">
<label for="ViewModel_Password">Password</label>
<input type="password" class="form-control" data-val="true" data-val-length="The Password must be at least 6 and at max 100 characters long." data-val-length-max="100" data-val-length-min="6" id="ViewModel_Password" name="ViewModel.Password">
<span class="text-danger field-validation-valid" data-valmsg-for="ViewModel.Password" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label for="ViewModel_ConfirmPassword">Confirm password</label>
<input type="password" class="form-control" data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="ViewModel_ConfirmPassword" name="ViewModel.ConfirmPassword">
<span class="text-danger field-validation-valid" data-valmsg-for="ViewModel.ConfirmPassword" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label for="ViewModel_Roles">Roles</label>
<input type="text" class="form-control" hidden="hidden" id="ViewModel_Roles" name="ViewModel.Roles" value="System.Collections.Generic.List`1[System.String]">
<span class="text-danger field-validation-valid" data-valmsg-for="ViewModel.Roles" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label for="Page_PageNumber">PageNumber</label>
<input type="number" class="form-control" hidden="hidden" data-val="true" data-val-required="The PageNumber field is required." id="Page_PageNumber" name="Page.PageNumber" value="1">
<span class="text-danger field-validation-valid" data-valmsg-for="Page.PageNumber" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label for="Page_PageSize">PageSize</label>
<input type="number" class="form-control" hidden="hidden" data-val="true" data-val-required="The PageSize field is required." id="Page_PageSize" name="Page.PageSize" value="5">
<span class="text-danger field-validation-valid" data-valmsg-for="Page.PageSize" data-valmsg-replace="true"></span>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="newRoles" value="Administrator">
<label class="form-check-label">Administrator</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="newRoles" value="User" checked="checked">
<label class="form-check-label">User</label>
</div>
<button type="submit" class="btn btn-success">Change</button>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Hsh_QOxexZLjyWnCjnNzz2ZhIuA-aPvi2MKBsCF12vrc6FY2yJnWGo1Nq9xNtwuiq7dTKdt93hUTJUf0PDD8RX1CJGgo0Jc3eDJMf8Ymh13fz0K60_S-uajXL3lNZalJJ58idjvok61tqa6oddepoWN1A0BUYHsk-h-PdfUCswqBSrt9GsHdbRvS5NrIitiZQ"></form>
Form data from google dev tools:
ViewModel.Password:
ViewModel.ConfirmPassword:
ViewModel.Roles: System.Collections.Generic.List%601%5BSystem.String%5D
Page.PageNumber: 1
Page.PageSize: 5
newRoles: User
__RequestVerificationToken: CfDJ8Hsh_QOxexZLjyWnCjnNzz2AyLo8vWEn4NIFS4brVjbJsYdFKgY97yj5IO8trooYDKkrdxPlFrGk2hmPQrmoEKgmGSno2jdOwGud-5Fcy8ewmp7K2pl1XODyKXxYSaZ3TngHSl1KLpMb9REpq4_Nqh45sdO1eBaMqpw3dfgCoAbvc6m2nEKJlDaRm_2eaKTX-w
Decoded form (the same as above):
ViewModel.Password=&ViewModel.ConfirmPassword=&ViewModel.Roles=System.Collections.Generic.List%601%5BSystem.String%5D&Page.PageNumber=1&Page.PageSize=5&newRoles=User&__RequestVerificationToken=CfDJ8Hsh_QOxexZLjyWnCjnNzz2AyLo8vWEn4NIFS4brVjbJsYdFKgY97yj5IO8trooYDKkrdxPlFrGk2hmPQrmoEKgmGSno2jdOwGud-5Fcy8ewmp7K2pl1XODyKXxYSaZ3TngHSl1KLpMb9REpq4_Nqh45sdO1eBaMqpw3dfgCoAbvc6m2nEKJlDaRm_2eaKTX-w
EDIT 2
I've changed the disable tag from id to readonly, and now ID is being sent. I don't thing I've changed anything else but I think thanks to that every single other property is added, but IList with roles. There still is a problem. Roles don't bind at all.
ViewModel.Id: fde0b182-3b24-4d5b-b31e-3680b7cfd4de
ViewModel.Password: 19923845379
ViewModel.ConfirmPassword: 1284326898838
ViewModel.Roles: System.Collections.Generic.List`1[System.String]
Page.PageNumber: 1
Page.PageSize: 5
newRoles: Administrator
newRoles: User
__RequestVerificationToken: CfDJ8Hsh_QOxexZLjyWnCjnNzz1Hy5YNNny4vPyGFd434Uybuo-O-dMFHT7eSKvd7JKA_dqxlQDIFlNzVsSjTDT6lzl7d2AU6Pj1nVRUyux3OZ2cGbyyBVKZHUI0Kq4u_MAx_b_29SUVSYh5Tpayc-0WPdcjGfxKLvL1qrbn6qeHcNk356VsPG1AC5cphft3frjILA
EDIT 3 [Solved]
Thanks to #itminus help I could solve the issue. Below you have changed form with two versions of the same - Roles with
<form asp-controller="Admin" asp-action="Update" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="ViewModel.Id"></label>
<input type="text" asp-for="ViewModel.Id" readonly class="form-control" />
<span asp-validation-for="ViewModel.Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ViewModel.Password"></label>
<input type="password" asp-for="ViewModel.Password" class="form-control" />
<span asp-validation-for="ViewModel.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ViewModel.ConfirmPassword"></label>
<input type="password" asp-for="ViewModel.ConfirmPassword" class="form-control" />
<span asp-validation-for="ViewModel.ConfirmPassword" class="text-danger"></span>
</div>
#for(int i = 0; i < Model.ViewModel.Roles.Count(); i++) {
<div class="form-group">
<label asp-for="ViewModel.Roles[i]"></label>
<input type="text" asp-for="ViewModel.Roles[i]" class="form-control" hidden="hidden" />
<span asp-validation-for="ViewModel.Roles[i]" class="text-danger"></span>
</div>
}
<div class="form-group">
<input type="number" asp-for="Page.PageNumber" class="form-control" hidden="hidden" />
<span asp-validation-for="Page.PageNumber" class="text-danger"></span>
</div>
<div class="form-group">
<input type="number" asp-for="Page.PageSize" class="form-control" hidden="hidden" />
<span asp-validation-for="Page.PageSize" class="text-danger"></span>
</div>
#foreach (var availableRole in (IList<IdentityRole>)ViewData["AllRoles"])
{
<div class="form-check">
<input class="form-check-input" type="checkbox" name="ViewModel.NewRoles[]" value="#availableRole.Name"
checked="#Model.ViewModel.Roles.Contains(availableRole.Name)">
<label class="form-check-label">#availableRole</label>
</div>
}
<button type="submit" class="btn btn-success">Change</button>
</form>
What is being sent from form now. (Example values)
ViewModel.Id: bf872461-f429-497f-8159-898e1dfafad9
ViewModel.Password: 1394657234609243070
ViewModel.ConfirmPassword: 2346-7345-67356667
ViewModel.Roles[0]: User
Page.PageNumber: 1
Page.PageSize: 5
ViewModel.NewRoles[]: Administrator
ViewModel.NewRoles[]: User
__RequestVerificationToken: CfDJ8Hsh_QOxexZLjyWnCjnNzz1AvzPUt8DrSfqpOni-Q65jAFnRqNs875teRTned_OQ6S7GV19WwWRqE7yRgTNmeeX9Twg4RjgQR_JEibtFYpHN6zbDJgLeauyyHxwOukRSTl0GZIRii5VaQBUxIbK6A8qHxgl4bn5-01YLj8bOXV9Ze7TvdP3MTX7ghYcAprPUJQ
Is naming convention wrong?
Yes. The name convention is :
Dot (.) represents property
[] represents collection index or dictionary
However, in your previous code, NewRoles fields have the name of newRoles:
<input ... name="newRoles" ...>
which is not correct. The same goes for the Roles property.
So you need change you code in following way:
Roles:
<label asp-for="ViewModel.Roles"></label>
<input type="text" asp-for="ViewModel.Roles" class="form-control" hidden="hidden" />
<span asp-validation-for="ViewModel.Roles" class="text-danger"></span>
#for(var i=0; i < Model.ViewModel.Roles.Count(); i++)
{
<input type="hidden" name="ViewModel.Roles[]" value="#Model.ViewModel.Roles[i]" />
}
NewRoles:
#foreach (var availableRole in (IList<IdentityRole>)ViewData["AllRoles"])
{
<div class="form-check">
<input class="form-check-input" type="checkbox"
name="ViewModel.NewRoles[]"
value="#availableRole.Name"
checked="#Model.ViewModel.Roles.Contains(availableRole.Name)">
<label class="form-check-label">#availableRole</label>
</div>
}

ASP.NET Core Model Binding: Using Dropdown List as Label

I am making an ASP.NET Core Mvc web app and am working on a search form. In the form, a user can be looked up by first name, last name, zip, and either ID, email, or phone. Whether a user is inputting ID, email, or phone is determined by a drop down list. I want to bind this to the User model I have but am not sure how to do it dynamically with the dropdown list. I am able to bind first name, last name, and zip just fine since they are not dynamic fields. Code for what I have so far for the form is below:
<form asp-action="Search">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label for="sel1">Search By:</label>
#* The dropdown menu to choose input type *#
<select class="form-control" id="sel1">
<option>ID</option>
<option>Email</option>
<option>Phone</option>
</select>
</div>
#* Where users would input information for the dropdown field *#
<div class="form-group">
<label for="id">Value:</label>
<input type="text" class="form-control clearable" id="id" Placeholder="0123456789">
</div>
<div class="form-group">
<label asp-for="FirstName">First Name:</label>
<input asp-for="FirstName" type="text" class="form-control clearable" id="firstName" Placeholder="Jane">
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LastName">Last Name:</label>
<input asp-for="LastName" type="text" class="form-control clearable" id="lastName" Placeholder="Doe">
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Zip">Zip Code:</label>
<input asp-for="Zip" type="text" class="form-control clearable" id="zipCode" Placeholder="55555">
<span asp-validation-for="Zip" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Search" class="btn btn-default" id="search" />
</div>
</form>
Then the code where the model is bound on the Search function:
public async Task<IActionResult> Search([Bind("FirstName, LastName, Zip")] Consumer consumer)
{
// Code....
}
Is there a way to dynamically bind the input for the text input with id="id" based on the dropdown menu selection? Thanks in advance.
There's two options:
Render all the fields to the page (first, last, zip, etc.), and then use JavaScript to hide/show those fields based on the selection in the drop down list. For example, if you select "First Name", then show the FirstName input and hide the others. The user then enters their keywords in that input, and when they post, it will bind to FirstName naturally.
Post the value of the drop down and a generic text input. In your action, you can then simply switch on the value of the drop down and query the right property:
IQueryable<Foo> query = db.Foos;
switch (model.MyDropDownSelection)
{
case "FirstName":
query = query.Where(x => x.FirstName.Contains(keyword));
break;
// etc.
}

Form fields from the ASP.NET View appear NULL in the Controller

The form fields do not return the value of the form even thought the asp-controller and asp-action is stated.
The form does go to the right controller function and returns the right view, however, it does the form object is NULL.
#using ActionAugerMVC.Models
#model Tuple<IEnumerable<Cities>,Content,IEnumerable<Content>,Quote>
#addTagHelper "*,Microsoft.AspNetCore.Mvc.TagHelpers"
<div class="sidebar__item">
<p class="subheading">Instant Quote Request</p>
<form class="register__form" role="form" asp-controller="Plumbing" asp-action="QuoteForm" method="post">
<div class="text-danger" asp-validation-summary="All"></div>
<div class="form-group">
<label class="sr-only">Full Name </label>
<input asp-for="#Model.Item4.FullName" type="text" class="form-control" placeholder="Full name">
</div>
<div class="form-group">
<label class="sr-only">Your phone</label>
<input asp-for="#Model.Item4.Phone" type="tel" class="form-control" placeholder="Your phone">
<span asp-validation-for="#Model.Item4.Phone" class="text-danger"></span>
</div>
<div class="form-group">
<label class="sr-only">E-mail</label>
<input asp-for="#Model.Item4.Email" type="email" class="form-control" placeholder="E-mail">
<span asp-validation-for="#Model.Item4.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label class="sr-only">Your Message</label>
<input asp-for="#Model.Item4.Message" type="text" class="form-control" placeholder="Your Message">
</div>
<input type="submit" value="Get a Quote Now" class="btn btn-accent btn-block">
</form>
</div> <!-- .sidebar__item -->
And the Controller looks like this, with the Quote object being null.
The hard coded, values appear correctly in the view, but the Quote object returned by the form is null.
[HttpPost]
public IActionResult QuoteForm(Quote quote)
{
if (ModelState.IsValid)
{
/* quote.FullName = "Umar Aftab";
quote.Email = "test#email.com";
quote.City = "Calgary";
quote.Message = "Test Message";
quote.Phone = "6474543769";
*/
}
return View(quote);
}
The issue is your use of a Tuple as your view's model combined with asp-for. For example, with something like:
<input asp-for="#Model.Item4.FullName" type="text" class="form-control" placeholder="Full name">
The name of the input is going to end up as Item4.FullName. However, your action accepts only Quote, which means the modelbinder needs the input to be named just FullName in order to bind it properly. You either need to accept the same model the view uses (though I've never tried posting a Tuple so not sure if that will even work), or you can use a partial view to work around the issue.
Essentially, you just would need to move all the fields related to just Quote to a partial view. Then, in this view, you can include them via:
#Html.Partial("_QuoteFields", Model.Item4)
That should be enough psych Razor out enough to just name the fields like FullName instead of Item4.FullName. If it's not, then you may need to reset the HtmlFieldPrefix, via:
#Html.Partial("_QuoteFields, Model.Item4, new ViewDataDictionary(ViewData) { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "" } })
The model on your view is different than the model you're trying to bind it to in the controller. You're not going to get the key/value pairs to match up
Put your razor in a partial view with Quote as the model and try that.
_QuoteForm.cshtml
#model Quote
<div class="form-group">
<label class="sr-only">Full Name </label>
<input asp-for="FullName" type="text" class="form-control" placeholder="Full name">
</div>
<div class="form-group">
<label class="sr-only">Your phone</label>
<input asp-for="Phone" type="tel" class="form-control" placeholder="Your phone">
<span asp-validation-for="Phone" class="text-danger"></span>
</div>
<div class="form-group">
<label class="sr-only">E-mail</label>
<input asp-for="Email" type="email" class="form-control" placeholder="E-mail">
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label class="sr-only">Your Message</label>
<input asp-for="Message" type="text" class="form-control" placeholder="Your Message">
</div>
OriginalView.cshtml
using ActionAugerMVC.Models
#model Tuple<IEnumerable<Cities>,Content,IEnumerable<Content>,Quote>
#addTagHelper "*,Microsoft.AspNetCore.Mvc.TagHelpers"
<div class="sidebar__item">
<p class="subheading">Instant Quote Request</p>
<form class="register__form" role="form" asp-controller="Plumbing" asp-action="QuoteForm" method="post">
<div class="text-danger" asp-validation-summary="All"></div>
#Html.Partial("_QuoteForm", Model.Item4)
<input type="submit" value="Get a Quote Now" class="btn btn-accent btn-block">
</form>
</div> <!-- .sidebar__item -->

Firing 'click' event on input submit without ID or name?

I am trying to auto-fill a form on a webpage using .NET's web browser int he C# language. I need to fire the submit button but it doesn't have a name or ID, all it has is a type and value.
The type is equal to "submit" and the value is equal to "Sign In"
Heres how I did it for Sign Up:
webBrowser1.Document.GetElementById("email").InnerText = email;
webBrowser1.Document.GetElementById("password").InnerText = password;
webBrowser1.Document.GetElementsByTagName("input")["register"].InvokeMember("click");
But this time, the submit button doesn't have a name, can someone guide me in the right direction to getting an element by its type or even better, value?
HTML:
<form accept-charset="utf-8" method="post">
<div class="field">
<label for="email">Email or Username</label> <span class="required">*</span> <input class="email" id="email" name="email" size="32" type="text">
</div>
<div class="field">
<label for="password">Password</label> <span class="required">*</span> <input id="password" name="password" size="16" type="password">
<p class="tip">I don't know my password</p>
</div>
<div class="field">
<input id="persistent_hidden" name="persistent" type="hidden" value="f"> <input checked="checked" id="persistent" name="persistent" type="checkbox" value="t"> <label for="persistent">Keep me logged in</label>
</div>
<div class="submit">
<input id="redirect_path" name="redirect_path" type="hidden"> <input type="submit" value="Sign In"> or <a class="cancel" href="/">Cancel</a>
</div>
</form>
try :
foreach(HtmlElement elem in webBrowser.Document.getElementByTagName("input")) {
if (elem.GetAttribute("value") == "Sign In") {
elem.InvokeMember("Click");
}
}

Categories

Resources