TextBoxFor value not passed to model when disabled - c#

I have a disabled input-field displaying data from a model.
<div class="form-group">
#Html.LabelFor(model => model.first_name, "Förnamn", new
{
#for = "inputFirstname",
#class = "col-lg-3 control-label"
})
<div class="col-lg-9">
#Html.TextBoxFor(model => model.first_name, new
{
#type = "text",
#class = "form-control",
#id = "inputFirstname",
text = Html.DisplayNameFor(model => model.first_name),
disabled="disabled"
})
</div>
</div>
I can submit this data to a controlelr method:
[HttpPost]
public ActionResult Index(RegistrationModel RegistrationModelViewModel)
{}
When i add disabled="disabled" the first_name data is null, if i remove it i get the correct data.
What am i doing wrong?

You may want to use readonly property, if you want to also display the data:
#Html.TextBoxFor(model => model.first_name, new
{
#readonly = "readonly"
})

You need to add an <input type="hidden" name="whateverName" /> on the page which matches the disabled field. By default, it will not be sent to the server.

Related

Combo Box clicked value to jQuery

In my ASP.NET MVC application, There are two combo boxes.
1st combo box contains the companies and with the selection, the second combo box loads the values.
Here when the user selects a value from the second combo box I need to get that value Id to the jQuery.
So far in my code, the selected value comes after the next selection. As an example, If I clicked a value, and again click another value then I get the ID of my previous selected value.
Can I get help to fix that, I need to get the selected value from the second combo box.
This is the HTML code
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group"> #Html.LabelFor(model => model.CompanyID, htmlAttributes: new { #class = "control-label col-md-6" }) <div class="col-sm-8"> #Html.DropDownListFor(model => model.CompanyID, Model.CompanyLists, "Select Company List", new { #id = "ddlComTypes" + Model.TempID, #class = "js-dropdown js-Com", #data_map = Model.TempID }) #Html.ValidationMessageFor(model => model.CompanyID, "", new { #class = "text-danger" }) </div>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group"> #Html.LabelFor(model => model.EmpId, htmlAttributes: new { #class = "control-label col-md-6" }) <div class="col-md-8"> #Html.DropDownListFor(model => model.EmpId, new List <SelectListItem>(), new { #id = "ddlEmpId" + Model.TempID, #class = "js-dropdown js-emp" , onchange = "OnSelectedIndexChange();" }) #Html.ValidationMessageFor(model => model.EmpId, "", new { #class = "text-danger" }) </div>
</div>
</div>
</div>
This is what I tried
< script type = "text/javascript" >
function OnSelectedIndexChange() {
var b = $('.js-Com').val();
var a = $('.js-emp').val();
alert(b);
alert(a);
}
<
/script>
You can just write an event handler for the second combo box:
$("#secondComboBox).on("change", function () {
const selectedId = $(this).val();
// You might want to int.parse($(this).val()) if you need an integer type.
});

How do I properly bind the html to the model data

So I am developing my first webpage using ASP.NET MVC and I managed to create a fully working registration page which send the data to the database and stored the user. Simple.
However I didn't really like the look and feel of the element it created for me so I thought I could change it out.
Original code WORKING
<div class="form-group">
#Html.LabelFor(model => model.Firstname, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Firstname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Firstname, "", new { #class = "text-danger" })
</div>
</div>
My new code NOT WORKING
<div class="row">
<div class="input-group bb-none">
<i class="fas fa-address-card"></i>
<input type="text" placeholder="Firstname">
</div>
</div>
I am 99.9% sure that it's a binding issue. I want the data I put into my new textbox
<input type="text" placeholder="Firstname">
To carry over the data to the model.
What's the part that binds it in the first option?
Tag helpers will resolve down to html and put the property name as both the id and name within the input. The model binder then binds to that.
#Html.TextBoxFor( m => m.Firstname, new { placeholder = "Firstname" })

Html.DropDownListFor not working for specific list in specific view

I use this method in my controller to add some lists to ViewBag which is used by two actions: Create and Edit. The lists are properly set, some items have set Selected property true.
private void AddUsersAndTrucksListsToViewBag(string[] selectedUsers, int[] selectedTrucks)
{
ViewBag.UsersList = uow.UsersRepository
.GetAll(_siteId)
.Where(u => u.IsActive)
.Select(u => new SelectListItem()
{
Value = u.Id,
Text = $"{u.Name} {u.Surname}",
Selected = selectedUsers != null && selectedUsers.Contains(u.Id)
})
.ToArray();
ViewBag.TrucksList = uow.OspRepository
.GetAllTrucks(_siteId)
.Select(t => new SelectListItem()
{
Value = t.Id.ToString(),
Text = $"{t.Codename} {t.Manufacturer} {t.Model}",
Selected = selectedTrucks != null && selectedTrucks.Contains(t.Id)
})
.ToArray();
}
In Edit view:
<div class="form-group">
#Html.Label("Osoby", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedUserIds, (SelectListItem[])ViewBag.UsersList, new { #class = "form-control", multiple = "multiple" })
</div>
</div>
<div class="form-group">
#Html.Label("Samochody", htmlAttributes: new {#class = "control-label col-md-2"})
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedTruckIds, (SelectListItem[]) ViewBag.TrucksList, new {#class = "form-control", multiple = "multiple"})
</div>
</div>
And exactly the same in Create view:
<div class="form-group">
#Html.Label("Osoby", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedUserIds, (SelectListItem[])ViewBag.UsersList, new { #class = "form-control ", multiple = "multiple" })
</div>
</div>
<div class="form-group">
#Html.Label("Samochody", htmlAttributes: new {#class = "control-label col-md-2"})
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedTruckIds, (SelectListItem[]) ViewBag.TrucksList, new {#class = "form-control ", multiple = "multiple"})
</div>
</div>
The problem is that everything works fine in Edit view. But in Create view only second list has properly rendered selected HTML attributes. This can be seen on the screenshots
What's wrong with this? I found that it can be caused by having the same ViewBag property name as some of Model property name but it is not.
Both lists have multiple attribute.
This is HTML generated by ListBoxFor()
<select class="form-control " id="SelectedUserIds" multiple="multiple" name="SelectedUserIds">
<option value="525b1890-942f-4fb4-96de-56e04b6ca196">Jan Kowalski</option>
<option value="5b0e1c01-0e46-436c-aa9b-ac63e66d691f">Adam Pawlak</option>
</select>
<select class="form-control " id="SelectedTruckIds" multiple="multiple" name="SelectedTruckIds">
<option selected="selected" value="3">425[O]21 MAN 12.232</option>
</select>
New screenshots:

Adding Html required to TextAreaFor not working c#

I'm trying to add a required to my TextAreaFor, but it won't give the error message when i post it. I'm trying to do it on the followinng line:
#Html.TextAreaFor(model => model.Content, new { htmlAttributes = new { #class = "form-control", required = "" } })
And this is my full code:
#using (Html.BeginForm("_Create", "Comments", FormMethod.Post))
{
#Html.HiddenFor(m => m.ThreadId)
<div class="form-group">
<div class="col-md-10">
#Html.TextAreaFor(model => model.Content, new { htmlAttributes = new { #class = "form-control", required = "" } })
#Html.ValidationMessageFor(model => model.Content, "", new { #class = "text-danger"})
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Post" class="btn btn-default" />
</div>
</div>
}
If anyone wanst to do it with html attribute,
#Html.TextAreaFor(model => model.Content, new { required = "required", htmlAttributes = new { #class = "form-control"} })
You don't need required as a html attribute. It should be a data annotation on the model.
[Required]
public string Content { get; set; }
#Html.TextAreaFor(model => model.Content, new { htmlAttributes = new { #class = "form-control", required = "" } })
Should be:
#Html.TextAreaFor(model => model.Content, new { #class = "form-control", required = "required" })
Or if you want to explicitly name the parameter your anonymous object is for:
#Html.TextAreaFor(model => model.Content, htmlAttributes: new { #class = "form-control", required = "" } })
But, if you do not use data-annotation, it could be even easier this way:
<textarea id="Content" name="Content" required class="form-control">#Model.Content</textarea>
(id attribute may be optional, depending on your usages.)
Side note: I tend to minimize uses of html helpers methods. For me, MVC is also about letting you control very precisely the browser client code, which is imo better done by writing it yourself. WebForm is, on this subject, about hiding most of browser client code handling.
Using extensively html helpers, built-in validation logic, and so on, may cause you to lose the precise control of how your page should work.

Viewmodel values not being returned to controller

I found some similar posts to mine, but I couldn't find an answer that suits my needs for this.
Problem is as follows:
I have a viewmodel like this:
public class PrefViewModel
{
public SelectList countries { get; set; }
public SelectList Provincies { get; set; }
public ApplicationUser user { get; set; }
public Preference MyPref{ get; set; }
public int mycountry { get; set; }
public int myprovince { get; set; }
}
my cshtml looks like this:
#using (Html.BeginForm("Index","Preferences", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(model => model.user.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
<span class="textvak">
#Html.TextBoxFor(model => model.user.UserName, new { disabled = "disabled", #readonly = "readonly" })
</span>
#Html.ValidationMessageFor(model => model.user.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
<span class="textvak">
#Html.TextBoxFor(model => model.user.Email, new { disabled = "disabled", #readonly = "readonly" })
</span>
#Html.ValidationMessageFor(model => model.user.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Unhashed, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.user.Unhashed, new { htmlAttributes = new { #class = "form-control", type = "password" } })
#Html.ValidationMessageFor(model => model.user.Unhashed, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Provincie.Land, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
#Html.DropDownListFor(model => model.mycountry, Model.countries, new { Name = "ddlLand", id = "ddlLanden", #class = "textvak" })
#Html.ValidationMessageFor(model => model.user.Provincie.Land, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Provincie, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
#Html.DropDownListFor(model => model.myprovince, Model.Provincies, new { #class = "textvak" })
#Html.ValidationMessageFor(model => model.user.Provincie, "", new { #class = "text-danger" })
</div>
</div>
<br />
<table>
<tr>
<td>
<input type="submit" value=#Resources.Wijzig class="btn btn-default" />
</td>
</tr>
</table>
}
and in my controller I try to get the posted PrefViewModel back as follows:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(PrefViewModel TestMymodel)
{
if (ModelState.IsValid)
{
int myCountry = TestMymodel.mycountry;
int myprovince = TestMymodel.myprovince;
}
return View();
}
My problem is that the PrefViewModel TestMymodel never is filled with the values I thought i'm posting back. Even more strange to me is the fact that I do get the Unhashed password back, but all other values are 0 or null.
I can put values inside the PrefViewModel to load the page and that works, but on Posting it's almost entirely empty.
Any ideas?
edit: Would it make any difference that I did change the default model to one that I made up myself? Cause when I Call the Create action for example, I do get the values back in my post (from create offcourse). I'm getting a bit desperate
edit2: this is what was posted:
__RequestVerificationToken:-JYcw0CH2zZ7WrGUiYJM6-R6VxfL41ykTD5EHUjgtyyFcN01AaUU61BYuaRNr4oPdEvDq09aYsOFdb8fObJTXMnTKulADVkGY8CrBG3U71QXw0g7Th86WKl1up4059Zy7mW0SlrWGJpehed586v_5g2
user.Unhashed:Jonas1234-
user.Unhashed:Jonas1234-
ddlLand:1
ddlProvincie:3
(can't add picture with my reputation, so here a link to the full post: http://postimg.org/image/id95wjcxp/ )
Ok, when I change the name of the dropdownlists to the PrefViewModel property name those values get returned correct.
It appears that you have overriden the names of the drop down lists to some values which are different than the property names in your view model. That's why the values are not successfully bound back. Make sure that your input fields respect the same names as the properties on your view model if you want the default model binder to be able to bind them back to the view model.
Also your username textbox has the disabled flag:
#Html.TextBoxFor(model => model.user.UserName, new { disabled = "disabled", #readonly = "readonly" })
so it will not be submitted back to the server. You might need to add an additional hidden field if you want those values to travel back. Or simply use readonly without disabled attribute. Both attributes prevent the user from modifying the value in the corresponding input field but in addition to that the disabled attribute strips it from the POST payload when the form is submitted.
So you may use:
#Html.TextBoxFor(model => model.user.UserName, new { #readonly = "readonly" })

Categories