Rey
Rey

Reputation: 4002

The string field is required. even thou there is no Required attribute in Asp.Net Core?

I am building a simple Asp.Net Core app in linux(pop os). I am using VueJs + Aps.Net Core 3.1.101 I am trying to do a POST call to my app and my model is like below:

public class AddConfigurationContextValueApiRequest
{
    public int ContextId { get; set; }

    [Required(ErrorMessage = "Value is required to continue")]
    [StringLength(500, ErrorMessage = "Value can not be longer than 500 characters")]
    public string Value { get; set; }

    [StringLength(500, ErrorMessage = "Display name can not be longer than 500 characters")]
    public string DisplayName { get; set; } 
}

As you can see there is not Required attribute for the DisplayName field, but whenever I pass a null value from VueJS app for this field I get The DisplayName field is required..

I am trying to figure out why would AspNet Core complain for this, since there is no Required attribute for such field!

Does anybody know if this intentional ? I tried to remove the StringLength attribute and still it triggers required attribute.

My action is fairly simple:

[HttpPost(UrlPath + "addConfigurationContextValue")]
public async Task AddConfigurationContextValue([FromBody]AddConfigurationContextValueApiRequest request)
{
    using var unitOfWork = _unitOfWorkProvider.GetOrCreate();
    if (!ModelState.IsValid)
    {
        //Here it throws because ModelState is invalid
        throw new BadRequestException(ModelState.GetErrors());
    }

    //do stuff

    await unitOfWork.CommitAndCheckAsync();
}

Upvotes: 6

Views: 10078

Answers (5)

Quan Truong
Quan Truong

Reputation: 341

Go to .csproj file and adding this :

<PropertyGroup>
   <Nullable>annotations</Nullable>
</PropertyGroup>

Upvotes: 0

SpaceGhost440
SpaceGhost440

Reputation: 579

Turns out there was a change to .net core that basically adds this code to all non-nullable types:

[Required(AllowEmptyStrings = true)]

You can read more about it here. You have two choices to fix this:

  1. You can mark all the non required types in your model as nullable.
  2. You can add this code to your startup in the AddMvc():
options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;

Upvotes: 0

Heinzlmaen
Heinzlmaen

Reputation: 967

Apparently .NET 6 Web APIs have the "Nullable" property added by default. I simply had to remove it.

.csproj file:

enter image description here

Edit: As Luke pointed out (without elaborating any further), the above behavior is working as intended and actually makes sense. If your JSON has a null value, your code might crash, if not handled. Throwing a compile time error is impossible, since the JSON is unknown. Forcing yourself to using nullable reference types makes the code more resilient.

I haven't checked yet, how swagger behaves, the default config surely doesn't care about a .NET 6 setting and will no longer flag mandatory fields, if you leave out the [Required] attribute and use only nullable reference types to point out what is mandatory and what isn't.

Upvotes: 5

The Thirsty Ape
The Thirsty Ape

Reputation: 1095

I have seen the same issue where the .csproj Nullable setting caused a property that was not marked as [Required] to act as though it were. I took a different approach than changing the Nullable settings in the .csproj file.

In my case it came down to a property that is required by the database; but the model allows null during POST as this particular property is a secret from the user. So I had avoided changing string to string? initially.

Once again, the Fluent API has provided an alternative solution.

Original Property

[JsonIgnore]
[StringLength(15)]
public string MyProperty { get; set; }

Updated Property

[JsonIgnore]
public string? MyProperty { get; set; }

Fluent API Directives (in your DbContext file)

protected override void OnModelCreating(ModelBuilder builder) {
  builder.Entity<MyClass>(c => {
    c.Property(p => p.MyProperty)
      .IsRequired()
      .HasMaxLength(15)
      .IsFixedLength();
  });
}

Upvotes: 5

Rey
Rey

Reputation: 4002

After @devNull's suggestion I found out that somehow while I was playing around with Rider IDE it seems it switched that feature on!

There is an option in rider that allows to change that configuration on project level:

If somebody has the same problem: right click on the project level, go to properties, Application and there you can see this configuration.

Thank you @devNull for the help :)

enter image description here

Upvotes: 4

Related Questions