Return empty error message in validation - asp.net

I want to return empty string for my validation in ASP.NET MVC 5 project. I have created a property in my view model:
[Required(ErrorMessageResourceType = typeof(TestResources), ErrorMessageResourceName = "Empty_Message", ErrorMessage = null)]
public int? TestProperty { get; set; }
Inside a view:
#Html.ValidationMessageFor(x => x.TestProperty)
When I try this one I get the default message "This field is required.". I want it to be empty in this case, because I add a class to error message's span element that shows up some icon.
I tried something like that:
[Required(ErrorMessage = "")]
public int? TestProperty { get; set; }
...but got an error:
Either ErrorMessageString or ErrorMessageResourceName must be set, but
not both.

Try setting a space. Example "Space". That would solve your problem.
[Required(ErrorMessage = " ")]
public int? TestProperty { get; set; }

you can use the following code:
[DisplayFormat(ConvertEmptyStringToNull=false)]
Reference for more details:
RequiredAttribute with AllowEmptyString=true in ASP.NET MVC 3 unobtrusive validation

Related

.NET 5.0 Web API won't work with record featuring required properties

I'm using a C# 9.0 record type as a binding model for a .NET 5.0 Web API project. Some of the properties are required.
I'm using the record positional syntax, but am receiving errors.
public record Mail(
System.Guid? Id,
[property: Required]
string From,
[property: Required]
string[] Tos,
[property: Required]
string Subject,
string[]? Ccs,
string[]? Bccs,
[property: Required]
Content[] Contents,
Attachment[]? Attachments
);
This is then exposed as the binding model for my Index action:
public async Task<ActionResult> Index(Service.Models.Mail mailRequest)
{
…
}
Whenever I try to make a request, however, I receive the following error:
Record type 'Service.Models.Mail' has validation metadata defined on property 'Contents' that will be ignored. 'Contents' is a parameter in the record primary constructor and validation metadata must be associated with the constructor parameter.
I tried removing the attribute on the Contents property, but it then fails for the next (prior) property. I tried using [param: …] instead of [property: …], as well as mixing them, but keep getting the same kind of error.
I looked around the web, and haven't found any suggestion of handling annotations differently for C# 9 records. I did my best, but I'm out of ideas—outside of converting my records to POCOs.
I gave up using Positional constructor, and with the verbose full declaration of the properties, it works.
public record Mail
{
public System.Guid? Id { get; init; }
[Required]
public string From { get; init; }
[Required]
public string[] Tos { get; init; }
[Required]
public string Subject { get; init; }
public string[]? Ccs { get; init; }
public string[]? Bccs { get; init; }
[Required]
public Content[] Contents { get; init; }
public Attachment[]? Attachments { get; init; }
public Status? Status { get; init; }
public Mail(Guid? id, string #from, string[] tos, string subject, string[]? ccs, string[]? bccs, Content[] contents, Attachment[]? attachments, Status status)
{
Id = id;
From = #from;
Tos = tos;
Subject = subject;
Ccs = ccs;
Bccs = bccs;
Contents = contents;
Attachments = attachments;
Status = status;
}
}
Try using only [Required] (instead of [property: Required]), for some reason worked for me
For me it started to work by adding the [ApiController] attribute to the controller.
I found something similar on ASP.NET Core Razor pages getting:
InvalidOperationException: Record type 'WebApplication1.Pages.LoginModelNRTB+InputModel' has validation metadata defined on property 'PasswordB' that will be ignored. 'PasswordB' is a parameter in the record primary constructor and validation metadata must be associated with the constructor parameter.
from
Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.ThrowIfRecordTypeHasValidationOnProperties()
After some digging, I found: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/ModelBinding/Validation/DefaultComplexObjectValidationStrategy.cs
So maybe as you've done, the verbose declaration is the way forward.
Positional record attributes in ASP.NET Core background
How do I target attributes for a record class? more background
Using FluentValidation and keeping properties with the full declaration seems to work perfectly in my case. I highly recommend trying this highly polished alternative validation library instead of using the pretty old standard data annotations
public record LoginViewModel
{
public string Mail { get; init; }
public string Password { get; init; }
public bool IsPersistent { get; init; }
}
public class LoginValidator : AbstractValidator<LoginViewModel>
{
public LoginValidator()
{
RuleFor(l => l.Mail).NotEmpty().EmailAddress();
RuleFor(l => l.Password).NotEmpty();
}
}

Asp.Net MVC Validations Not working

[Display(Name = "SentDoc_lblDescription ", ResourceType = typeof(EXTDocuments.Resources))]
[Required(ErrorMessage="Description Required")]
public string Description {get;set;}
This Description Property is required in business logic.
When I am clicking submit button it throws an error.
The error is decription is null, I want to validate that property from within the UI.
I want to recall running into something like this and currently use this attribute set in order to ensure my strings get validated correctly:
[Required]
[MaxLength(200)]
[MinLength(5)]
[Display(Name = "Name")]
public string ItemName { get; set; }
By using the MinLength and Required, you get a required string with a minimum length. Hopefully this helps you out.

ASP.NET MVC 5 prevent value changes

When I update my website, it hints me this problem "{"The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated."}"
The screenshot is list below, there is a value named RecordDate, it has value, but I will not change anything about that value so I didn't display it on the screen.
The problem is MVC automatically update that value for me, and the value of the date becomes 0000-00-01 i think, maybe something else, how to prevent it? just keep the origin value and update other columns.
The model class looks like this
public class ShiftRecord
{
public int ID { get; set; }
public int EmployeeID { get; set; }
[Display(Name="Company Vehicle?")]
[UIHint("YesNo")]
public bool IsCompanyVehicle { get; set; }
[Display(Name="Own Vehicle?")]
[UIHint("YesNo")]
public bool IsOwnVehicle { get; set; }
//Problem comes from this line
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString="{0:yyyy-MM-dd}")]
public DateTime RedordDate { get; set; }
[Display(Name="Day Type")]
public Nullable<DayType> DayType { get; set; }
[Display(Name="Normal Hrs")]
public Nullable<int> NormalHours { get; set; }
[Display(Name="Time and Half Hrs")]
public Nullable<int> TimeAndHalfHours { get; set; }
[Display(Name="Double Time Hrs")]
public Nullable<int> DoubleTimeHours { get; set; }
[Display(Name="Shift Hrs")]
public Nullable<int> ShiftHours { get; set; }
public string Comment { get; set; } // System manager can leave any comment here
public bool IsRead { get; set; } // has this shift record been read
public virtual Employee Employee { get; set; }
public virtual ICollection<JobRecord> JobRecords { get; set; }
}
In the controller, I didn't change anything about the model, so it looks like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,EmployeeID,IsCompanyVehicle,IsOwnVehicle,RecordDate,DayType,NormalHours,TimeAndHalfHours,DoubleTimeHours,ShiftHours,Comment,IsRead")] ShiftRecord shiftrecord)
{
if (ModelState.IsValid)
{
db.Entry(shiftrecord).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.EmployeeID = new SelectList(db.Employees, "ID", "LastName", shiftrecord.EmployeeID);
return View(shiftrecord);
}
And I didn't change Edit view as well, the only thing is I made RecordDate unchangeable, changed it from #Html.EditorFor to #Html.DisplayFor
<div class="form-group">
#Html.LabelFor(model => model.RedordDate, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.RedordDate)
#Html.ValidationMessageFor(model => model.RedordDate)
</div>
</div>
Your issue is .net uses a default 1/1/0001 datetime min value, and the sql minimum value is 1/1/1753, which is incompatible. If you use datetime?, it will resolve as null and work OK, or put in code to update the date to a default value before committing to the database.
Your understanding is incorrect. ASP.NET MVC did not automatically update the value for you, the problem arises because you did not post RedordDate to the controller action so RedordDate will have its default value (i.e. default(DateTime)).
DateTime is a value type in .NET such that it cannot be null and its default value is DateTime.MinValue (i.e. 01/01/0001 00:00:00).
You can solve it by making the RedordDate property Nullable by changing its type from DateTime to DateTime? so that it accepts null values.
One thing to note is that if you save this value back to a SQL Server but your underlying SQL datatype is datetime instead of datetime2, you will receive an exception since 01/01/0001 00:00:00 is out-of-range in datetime
Further reading:
MSDN recommends using datetime2 in a new development
Difference between value types and reference types explained by Jon Skeet
You do render any controls for property RedordDate so when you post back, the DefaultModelBinder initializes a new instance of ShiftRecord and RedordDate has a value of DateTime.MinValue (1/1/0001).
Add a hidden control for the property to post it back
#Html.HiddenFor(m => m.RedordDate)
Then in the POST method, remove the [Bind] attribute. Currently, even if the value is posted back, it will not bind because it has been excluded from the Include list. You have RecordDate but not RedordDate (a typo?). Note by default all properties will be bound so the attribute is not necessary unless you are specifically excluding properties.
A better alternative is to create a view model that contains only those properties you want to display and edit (What is a view model in MVC) and then in the POST method, get the original data model and map the view model properties to it.
Side note: Can the vehicle be both IsCompanyVehicle and IsOwnVehicle?

Prevent user from submitting default form values in .NET MVC3

I have the following model:
public class Contact
{
public Contact()
{
Name = "Your Name";
Email = "Your Email";
Message = "Your Message";
}
[Required]
[StringLength(60,MinimumLength = 3)]
public string Name { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[RegularExpression(#"\b[A-Z0-9._%-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b")]
public string Email { get; set; }
[Required]
[StringLength(2200, MinimumLength = 10)]
[DataType(DataType.MultilineText)]
public string Message { get; set; }
}
For Message and Name, their default values (in the constructor) actually pass validation, obviously that is bad. I know I could check for this and throw an error in the Controller, but I'm trying to find a way to do these in the model (as I assume that is the correct place to do it).
I wouldn't do this at all server side. Use a textbox watermark ala one of the many methods for ex.
http://code.google.com/p/jquery-watermark/
Those look like hints, not default values. You should implement these with javascript, instead of setting them as input values.

DataAnnotation attributes not working in Asp.Net MVC2

I am having trouble with the with mvc2.
I am using the Entity Framework as my ORM. I have used the POCO Entity Generator to create POCO objects. I moved the generated objects to a separate project. I followed steps outlined here(Tutorial). This is my project structure
Sports.Data - Entity Frmework and Data Access
Sports.Entities - The poco objects generated and buddy classes
Sports.Web - The web application
In the Sports.Entities project I have created buddy classes for the generated pocos.
The problem I am having is that the attributes are being ignored by the mvc. The validation is not working and the correct label text is not being displayed. Instead of 'Shirt Size', 'ShirtSize' is displayed.
What am I doing wrong?
Thanks for any help.
Here is the code.
<div>
<%: Html.LabelFor(m => m.Player.ShirtSize)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(m => m.Player.ShirtSize) %>
<%: Html.ValidationMessageFor(m => m.Player.ShirtSize)%>
<div>
namespace Sports.Entities
{
[MetadataType(typeof(PlayerMetadata))]
public partial class Player
{
public double PointsPerGame {
get { return (double) this.Points / this.MatchesPlayed; }
}
}
public class PlayerMetadata
{
[Required(AllowEmptyStrings = false, ErrorMessage = "First Name is required.")]
[StringLength(50, ErrorMessage = "First Name must be 50 characters or less")]
[DataType(DataType.Text)]
object FirstName { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Last Name is required.")]
[StringLength(50, ErrorMessage = "First Name must be 50 characters or less")]
[DataType(DataType.Text)]
object LastName { get; set; }
[Required(ErrorMessage = "Shirt Size is required.")]
[EnumDataType(typeof(ShirtSizeEnum), ErrorMessage = "Shirt Size is invalid.")]
[DisplayName("Shirt Size")]
object ShirtSize { get; set; }
[Required(ErrorMessage = "Gender is required.")]
[EnumDataType(typeof(GenderEnum) , ErrorMessage = "Gender is invalid.")]
object Gender { get; set; }
[Required(AllowEmptyStrings = false , ErrorMessage = "Date of birth is required.")]
[DataType(DataType.Date)]
object DateOfBirth { get; set; }
}
}
Thanks for your answer. I figured out the problem. The properties in the buddy classes need to be public. Everything started working after I made the properties public.
public object ShirtSize { get; set; }
Hmm, the code you posted look pretty solid. Is your view strongly typed and inheriting the appropriate class?
Inherits="System.Web.Mvc.ViewPage(Of YourWebApp.Sports.Entities.Player)
also, this might sound like a dumb question, but are you passing the populated Player object back to the view both when you first populate the view and when you post it back? and finally are you making sure to check
if ModelState.IsValid?

Resources