Suppress validation attributes for Razor Pages property - asp.net

MyPage.cshtml.cs
[ValidateNever] // <-----
public string ProductName { get; set; }
MyPage.cshtml
<input asp-for=#Model.ProductName />
That renders:
<input type="text" data-val="true" data-val-required="The ProductName field is required." id="ProductName" name="ProductName" value="">
I expected [ValidateNever] would suppress validation attributes, but they are emitted anyway.
How can I suppress them?

From .NET 6+ the non-nullable property must be required, otherwise the ModelState will be invalid.
The easist way, change your code like below:
[ValidateNever] // <-----
public string? ProductName { get; set; }

Related

Remote validation model binding not working on a razor page in dotnet core 2.0

I have a form in a razor page with a field that has remote validation..
. . .
<div class="form-group">
<label class="control-label" asp-for="ReportViewModel.ExecSql"></label>
<textarea class="form-control" asp-for="ReportViewModel.ExecSql" ></textarea>
<span asp-validation-for="ReportViewModel.ExecSql" class="text-danger"></span>
</div>
. . .
The field in the ReportViewModel is defined as:
. . .
[Remote(action: "VerifySql", controller: "ReportService", HttpMethod = "POST")]
public string ExecSql { get; set; }
To call the action below:
[AcceptVerbs("Post")]
public IActionResult VerifySql(string ExecSql)
{
if (!Repository.VerifySql(ExecSql))
return Json("Sql is not valid (Select statements only are allowed)");
return Json(data: true);
}
The razor page cs file:
public class AddReportModel : PageModel
{
private readonly IIntegrityReportRepository _repository;
private readonly IMapper _mapper;
public AddReportModel(IIntegrityReportRepository repository, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}
[TempData]
public string ConfirmationMessage { get; set; }
[BindProperty]
public IntegrityReportViewModel ReportViewModel { get; set; }
. . .
This calls the action but ExecSql is always null. This is because when I look at the request, the form is posting.. ReportViewModel.ExecSql. Which I cannot pick up from my VerifySql action method.
I have tried adding a name to the cshtml field:
<textarea class="form-control" asp-for="ReportViewModel.ExecSql" name="ExecSql" ></textarea>
This then does bind the field and pass the value, however the client side validation does not work when it is passed back.
I can get it working by defining ANOTHER field in the cs razor page file e.g.
[Remote(action: "VerifySql", controller: "ReportService", HttpMethod = "POST")]
[BindProperty]
public string ExecSqlField { get; set; }
And then changing the cshtml to:
<div class="form-group">
<label class="control-label" asp-for="ExecSqlField"></label>
<textarea class="form-control" asp-for="ExecSqlField"></textarea>
<span asp-validation-for="ExecSqlField" class="text-danger"></span>
</div>
However this feels wrong and I am then duplicating the viewmodel which I need to share across another pages. Is there anyway to pick up the field in the original viewmodel in my action method by somehow getting the Verify action method to access ReportViewModel.ExecSql?
Many thanks for any help
Just wanted to add that #Baseless and #Breno did have the correct answer.
My property was as such:
[Display(Name = "Access Code")]
[Remote("CheckForGroup", "Users", "Admin", HttpMethod = "Post")]
public string AccessCode { get; set; }
and it only worked when I added this to my controller:
public IActionResult CheckForGroup([Bind(Prefix = "Input.AccessCode")] string accessCode)
Thank you guys!
Afte banging heads a lot, I found a workaround. Not the most elegant but it is doing the job right now.
Just add [Bind(Prefix = "ReportViewModel.ExecSql")] to your validation method parameter.
You can revert the changes and resume using the "Model.Field" form pattern.

How can I access model property inside viewmodel using asp-for?

I have this model
public partial class MtbWarehouse
{
public int Idhwarehouse { get; set; }
public string Namewh { get; set; }
}
I implement the model in this view model
public class WarehouseViewModel
{
public MtbWarehouse Warehouse { get; set; }
public string ListAction { get; set; } = "Index";
}
And I am using WarehouseViewModel in view
#model ViewModel.warehouseviewmodel
<input type="text" asp-for="Warehouse" class="form-control" placeholder="">
How can I access Namewh using asp-for because this asp-for thing is better than using
#Html.TextBoxFor()
If you are after rendering an input text element for Namewh property of the Warehouse property of your view model, you can use the dot notation to access a child properties' property. Like this
<form asp-action="Index" asp-controller="Home">
<input type="text" asp-for="Warehouse.Namewh" />
<input type="submit"/>
</form>
This will generate an input text element with name Warehouse.Namewh and will render the value of that property if you set that from your GET action method.
VS Intellisense may still show this as invalid with red color. But when this code is executed, the tag helper will generate the correct input field with the value

ASP MVC Remote Validation Removing Area

I have the following Model:
public class UserModel
{
[Required]
public String Name {get; set; }
[Required]
public String Surname {get; set; }
[Required]
[Remote("ValidateIdNumber", "CustomValidation", "", ErrorMessage = "Invalid ID")]
public String IDNumber {get; set; }
}
I have a create user form that is the Admin area. So it's "/Admin/User/Create".
My "ValidateIdNumber" action is in the root in the controller "CustomValidation"
So to access it you would need to go to "/CustomValidation/ValidateIdNumber"
public Boolean ValidateIdNumber(String IDNumber) {
//Validate ID number and return result.
}
The problem is that when the form gets created, the remote validation targets "/Admin/CustomValidation/ValidateIdNumber".
<input class="text-box single-line" data-val="true" data-val-remote="Invalid ID" data-val-remote-additionalfields="*.IDNumber" data-val-remote-url="/Admin/CustomValidation/ValidateIdNumber" data-val-required="Please provide a ID Number" id="IDNumber" name="IDNumber" type="text" value="">
How can I remove the Area? I've tried making the area parameter in the Remote attribute an empty string("") and null.
any ideas? I want to try and keep my validation in the root and not in areas.
You can write a custom remote attribute , see here:
ASP.NET MVC 3 Remote Validation

The LoginModel RememberMe is being marked as required field

I am using the LoginModel inside asp.net mvc web application which looks as follow:-
public class LoginModel
{
[Required(ErrorMessage = "Required")]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required(ErrorMessage = "Required")]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
but the generated mark-up is as follow:-
<div class="input-prepend">
Remember Me ? <input data-val="true" data-val-required="The Remember me? field is required." id="RememberMe" name="RememberMe" type="checkbox" value="true" /><input name="RememberMe" type="hidden" value="false" />
</div>
So why the RememberMe is being marked as Required fields , although inside the model class there is no [Required] data annotation specified?
Change the property to use a nullable bool:
[Display(Name = "Remember me?")]
public bool? RememberMe { get; set; }
That way you declare that no value given to this property is OK, which means it can be optional. By using a normal bool, MVC renders a required error since that property must be either true or false.
EDIT:
Based on your comments, it seems that RememberMe should not be optional, since a NULL value is not satisfactory. In that regard, having RememberMe as bool is the way to go. Yes you will get the data-val-required stuff in the HTML, but it sounds like that's fine.
EDIT:
OK I see where you're coming from. You really don't want a red asterix next to the Remember Me checkbox then you must define RememberMe property as bool?
Then, when the user submits their data, if RememberMe.Value is null, can you manually set RememberMe.Value to false? Because if the user has not ticked the box, that means they do not want the site to remember them. If you can set the value to false yourself, so that you're not passing NULL to SetAuthCookie, then you'll be fine.

How to param binding with asp .net mvc when there's dot in the name?

I have the following code in my view
<input class="form-control" type="text" name="dev" value="foobar" />
In the controller I have
public ActionResult BobLobLaw(string dev)
The above works well. But then I changed my view model, now my view code becomes like
<input class="form-control" type="text" name="arrested.dev" value="foobar" />
How should I name my action param so that it will bind to the new input name ("arrested.dev") ?
Additionally, looking on how to do this for enum type as well. e.g.
<% Html.DropDownList("arrested.devEnum", SelectList) %>
public ActionResult BobLobLaw2(suitEnum arrested.devEnum)
The modelbinder interprets a . to mean a property on an object. So you would need some object with a property of dev as a parameter:
public class Arrested
{
public string dev { get; set; }
}
Then:
public ActionResult BobLobLaw(Arrested arrested)
{
...
}

Resources