Reputation: 61
I'm start work with .NET 6 Web API. I have write a very simple controller:
[Route("[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet,Route("sample")]
public IActionResult ReturnSample(string ParameterOne, string ParameterTwo)
{
[... do something ...]
}
}
The problem is that all parameter are mandatory.
URL: https://<server>/test/sample?ParameterOne=Value&ParameterTwo=Value
Works fine, all OK
URL: https://<server>/test/sample?ParameterOne=Value&ParameterTwo=
ERROR:
{
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"00-dc73d9983b53750d2073c48bec522c70-98fe251af1accccf00",
"errors":{"ParameterTwo":["The ParameterTwo field is required."]}}
How can I allow an empty value as a valid value for parameter?
Thanks Lorenzo
Upvotes: 6
Views: 12757
Reputation: 71
In C# 8, a Nullable Reference Type Feature was introduced, which helps identify when a type is null and aids in preventing NullExceptions. It essentially gives you CS8618 warnings throughout your code to let you know that you might want to consider changing reference types to be nullable. With that said, this also changes how the compiler interprets the C# code.
This compiler interpretation change requires you to set your optional reference type parameters for your controller endpoint to be nullable. In this case: string?
.
This feature is said to be defaulted to disabled, but when I built a .Net 6 project it was enabled (maybe I accidentally clicked a checkbox that enabled it or something when I built the project).
With the Feature Enabled:
Declare the optional string parameters as nullable: string?
public class TestController : ControllerBase
{
[HttpGet("sample")]
public IActionResult ReturnSample(string ParameterOne, string? ParameterTwo, string? ParameterThree)
{
[... do something ...]
}
}
This supports the following URLs:
- https://{domainName}/test/sample?ParameterOne=Value
- https://{domainName}/test/sample?ParameterOne=Value&ParameterTwo=Value
- https://{domainName}/test/sample?ParameterOne=Value&ParameterThree=Value
- https://{domainName}/test/sample?ParameterOne=Value&ParameterTwo=Value&ParameterThree=Value
- https://{domainName}/test/sample?ParameterThree=Value&ParameterOne=Value
NOTE: Notice that ParameterOne is in all of the above URLs, this is because it is required, due to NOT being a nullable string string?
. In addition, notice that the query parameter order doesn't matter, the controller will map the query to your endpoint's parameter names (this is called Model Binding).
[HttpGet("sample")]
public IActionResult ReturnSample(string ParameterOne, string? ParameterTwo = "test2", string? ParameterThree = "test3")
With the Feature Disabled:
using System.ComponentModel.DataAnnotations;
public class TestController : ControllerBase
{
[HttpGet("sample")]
public IActionResult ReturnSample([Required] string ParameterOne, string ParameterTwo, string ParameterThree)
}
NOTE: Notice that the required parameter ParameterOne has the [Required] attribute associated with it. This will require that parameter when the endpoint is called. [Required] comes from the System.ComponentModel.DataAnnotations namespace and is a Validation Attribute. If you want all reference type parameters to be required use [FromQuery]
This endpoint will support the same URLs that are listed above in the Feature Enabled Section.
If you don't want the missing query parameters to be interpreted as null when the endpoint is hit, then you can set the string(s) to have default values. Remember when adding default values to a parameter it makes it optional and optional parameters must go at the end of the parameter list (or end of argument):
[HttpGet("sample")]
public IActionResult ReturnSample([Required] string ParameterOne, string ParameterTwo = "test2", string ParameterThree = "test3")
Enabling/Disable The Nullable Reference Type Feature
WARNING: Enabling/Disabling the Nullable Reference Type Feature will affect how your code is read by the compiler and may incur major side effects. If you are just starting a project, like me, then this change shouldn't affect anything.
.csproj
file (double-click on your project)<Nullable>disable</Nullable>
to <Nullable>enable</Nullable>
or vice versa.Upvotes: 4
Reputation: 2032
If you don't want to send value at all, you can try using ?
:
[HttpGet("{ParameterOne?}/{ParameterTwo?}"),Route("sample")]
public IActionResult ReturnSample(string ParameterOne = null, string ParameterTwo = null)
{
[... do something ...]
}
Note: if you have two parameters and just one of them could have a value, then the second parameter that has value as null
should be always in your uri
in the end:
[HttpGet("{ParameterOne?}/{ParameterTwo}")] => wrong
[HttpGet("{ParameterTwo}/{ParameterOne?}")] => correct
Upvotes: 1
Reputation: 141600
You can set the default value for the second parameter:
[HttpGet,Route("sample")]
public IActionResult ReturnSample(string ParameterOne, string? ParameterTwo = null)
{
// ...
}
Upvotes: 1