.Net Core Swagger not working with Required enum? - asp.net-core

Using Swashbuckle 5.6.3. Controller method looks like:
public async Task<IActionResult> GenerateTokenAsync([FromForm] TokenCredentials tokenCredentials)
TokenCredentials looks like:
[Required]
public GrantType? grant_type
{
get;
set;
}
GrantType looks like:
public enum GrantType
{
client_credentials = 0
}
The enum shows in Swagger and shows as required, but when I hit the execute button, I get the red bounce of death. If I take off the Required, then it executes. I also tried NotNull, but that let it through regardless.
Am I missing something?

You can use Swashbuckle.AspNetCore 5.5.0,it's OK. Here is an official document
Result:
Or you can delete [FromForm] in Swashbuckle 5.6.3.

Related

Where does this "Required" attribute for the Swagger UI coming from for ASP.NET?

I have the following in my ASP.NET Controller:
[Produces("application/json")]
[Consumes("application/json")]
[Route("api/[controller]")]
[ApiController]
public class ConnectionManagersController : ControllerBase
{
[HttpGet("{connectionManagerID:int}")]
[ProducesResponseType(typeof(ConnectionManagerModel), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ConnectionManagerModel>> GetConnectionManagerAsync(int connectionManagerdID){}
}
However when I run the app and the Swagger UI comes up I get the following screen:
There are TWO connectionManagerID fields on the Swagger UI - the first is an int (which is should be) and the second is a string and is required which I dont know where that is coming from.
I dont know where the *required field is coming from.
The parameter connectionManagerdID is an int - it is not nullable so in effect it is required.
Try this:
public async Task<ActionResult<ConnectionManagerModel>> GetConnectionManagerAsync(int connectionManagerdID = null){}
It should set it to optional.
it is from here, you will probably get 404, if you don't supply id to url.
[HttpGet("{connectionManagerID:int}")]
and if you don't want to be required try this
[HttpGet("{connectionManagerID?:int}")]
in this case maybe it makes sense to change the action too
public async Task<ActionResult<ConnectionManagerModel>> GetConnectionManagerAsync(int? connectionManagerdID){}
or you can keep what you have. It will be 0 by default.
I had the two parameters spelled differently. :(

Validate existing entity in CQRS + EventSourcing. Microservice ASP.NET Core 5.0

I am currently building an app, and I would like to use micro services.
I use Mediatr for implementing a CQRS pattern and EventStore for event sourcing.
I have a problem with checking that an entity exists before creating an event of aggregate and appending it to the EventStore.
For example: I have LanguageAggregateRoot
public class LanguageAggregateRoot
{
public Guid Id {get;set}
public string Code { get; private set; }
public string Name { get; private set; }
public bool Enable { get; private set; }
public string Icon { get; private set; }
}
Field Code is unique and user can change code for language.
When I use Code field for stream id of eventstore, if the user sends a CreateLanguageCommand and ChangeCodeCommand, I need to check that the new code exists.
So I use Id field for stream id. But I don't understand how I can validate whether code field is unique?
As far as I've found out should not use query handling in command handling.
If i use client to check existed then send command to server. I think it doesn't look good. Because something/someone can request only command with out my client.
How can I do that?
Thanks for your support.
It should be fine to validate your request in your command itself.
you can use the below link for more details.
CQRS - is it allowed to call the read side from the write side?

sitefinity widget using query string

I like to build a widget that will take in the query string as parameters. Is there a build in method for this in sitefinity? Or is this something I have to do in code? I like to leverage sitefinity toolset .
domain.com/shoes?type=sneakers&sort=price_ascending
namespace SitefinityWebApp.Mvc.Controllers
{
[ControllerToolboxItem(Name = "Shoes", Title = "Shoes", SectionName = "MVC")]
public class ShoesController : Controller
{
public string type{ get; set; }
public string sort{ get; set; }
Should take in routed parameters like a regular MVC controller. So like
public ActionResult Index(string type, string sort){
this.sort = sort;
this.type = type;
....
}
There's nothing to automatically hydrate those public properties (and thank god, can you imagine the havok if someone could change them arbitrarily?)
But you can use Telerik.Sitefinity.Services.SystemManager.CurrentHttpContext to get the HTTP context that has the regular Request.Querystring to use.
Think of Sitefinity more as like a regular ASP.NET MVC site, with API helpers instead of a magic "do it the sitefinity way" kinda thing you know :) The ability to have multiple controllers on a page is GREAT.

What's causing the parameter to be null?

I am using Asp.Net Core 2.0 and web api to build a rest service. All works fine except for HTTPPost.
[HttpPost("LoginUser")]
public IActionResult LoginUser(LoginUser loginUser)
{
return Ok(loginUser);
}
loginUser is always null. I am testing with fiddler and my route is http://localhost:53250/api/User/LoginUser
and the body is
{"EmailAddress":"xx#xx.com","Password":"123456789"}
Fiddler hits the link just fine, but payload is always null.
I have also tried
[HttpPost("LoginUser")]
public IActionResult LoginUser([FromBody] LoginUser loginUser)
{
return Ok(loginUser);
}
In this case, it doesn't hit the function.
This is the LoginUser definition:
public class LoginUser
{
public string EmailAddress { get; set; }
public string Password { get; set; }
}
Any Ideas?
Your action should be:
[Route("api/[controller]")]
public class UserController : Controller
{
[HttpPost("LoginUser")]
public IActionResult LoginUser([FromBody] LoginUser loginUser)
{
return Ok(loginUser);
}
}
See, [HttpPost("LoginUser")] affects only route and doesn't relate to LoginUser object type.
Update: you need [FromBody] as ASP.NET Core model binding by default looks into [FromForm] binding source. And [FromBody] attribute indicates that you want to bind a parameter to data in the request body.
Update 2: you also should add Content-Type: application/json header to request. ASP.NET Core selects input formatters based on the this header.
Update 3: if you really need to get body data as raw string, look into ASP.NET Core MVC : How to get raw JSON bound to a string without a type?. It suggests using [FromBody] dynamic data
JSON parsing is case sensitive. Your JSON is in the wrong case.
Should be: {"EmailAddress":"xx#xx.com","Password":"123456789"}.
Issue has been solved. When I added my UserController, I did so as a class and derived from controller. I deleted it and added it as a new item and picked web api core controller. Now all is working just fine. Thanks for your help.
If you have properties in your request model that are set to {get;
private set;}, the values will not get populated. Make them public by removing private. Also constructors
aren't utilized.
If you're reading plain text from the body, see if [FromForm]
works.

Support aliased arguments in get requests for web api

Background
I have a web api project which uses complex types for GET requests, here is an example of a controller method, and its associated complex type
[RoutePrefix("api")]
public class MyController : ApiController
{
[Route("Something")]
public IHttpActionResult GetSomething([FromUri]RequestObject request)
{
// do something to get "data"
return Ok(data);
}
}
// elsewhere
public class RequestObject
{
[Required]
public string SomeValue{get;set;}
}
This works with a url such as http://domain.com/api/Something?SomeValue=foo.
I would like to use alias' for these parameters, for which I will do some complex stuff (once I have this working) but effectively I have defined an attribute AliasAttribute.
[AttributeUsage(AttributeTargets.Property,AllowMultiple=true)]
public class AliasAttribute : Attribute
{
public string ParameterName { get; private set; }
public AliasAttribute(string parameterName)
{
this.ParameterName = parameterName;
}
}
Which I would like to adorn onto my request model like so:
// elsewhere
public class RequestObject
{
[Required,Alias("val")]
public string SomeValue{get;set;}
}
Allowing my url to shorten to http://domain.com/api/Something?val=foo. This is a contrived and simplified example, but hopefully demonstrates the background.
Problem
ModelBinding in web api has become very complex compared to Mvc model binding. I am getting twisted up between IModelBinder, IValueProvider, HttpParameterBinding et al.
I would like an example of where I should hook in to the model binding to allow me to write the value to my model from the querystring - note that I only use this aliasing behaviour when the route uses the FromUri attribute (see MyController.GetSomething above).
Question title: Support aliased arguments in get requests for web api. I think you are re-inventing a wheel here AliasAttribute , and have not given a really good reason why you don't want to use community ways of doing this.
I have done something similar with Newtonsoft.Json serializer. But if you want something ootb I'd have to google around.
public class RequestObject
{
[Required]
[JsonProperty("vla")]
public string SomeValue{get;set;}
}
Example SO that uses it: .Net NewtonSoft Json Deserialize map to a different property name
Here is a more agnostic way to do it.
[DataContract]
public class RequestObject
{
[DataMember(Name="val", IsRequired=true)]
public string SomeValue{get;set;}
}