What's causing the parameter to be null? - asp.net-core

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.

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. :(

.Net Core Swagger not working with Required enum?

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.

Web Api routing with parameter option?

I would like to provide a ASP.Net Web API that can be called by the following formats:
http
://myApiServer/API/MyLookupMethod/GetForIVR/PhoneNumber/8005551212
or
http
://myApiServer/API/MyLookupMethod/GetForIVR?LookupType=PhoneNumber&LookUpValue=8005551212
Is it possible to set up a route that works with either call?
My current route is
config.Routes.MapHttpRoute(
name:"MyRoute",
routeTemplate:"api/{controller}/{action}/{Lookuptype}/{lookupvalue}"
);
Try to use attribute routing
[Route("api/user/YourMethodName/{id}/{param2}")]
[HttpGet]
public HttpResponseMessage YourMethodName(int id = 0, bool param2= true)
Hope it works!!
You can use Attribute based routing i.e. specific routing on controllers and methods. Further you should pass your 2 parameters as query-string like in this URL MyLookupMethod/GetForIVR?LookupType=PhoneNumber&LookUpValue=8005551212 and they will be automatically parsed as method parameters.
public class SomeController : ApiController
{
// GET MyLookupMethod/GetForIVR?LookupType=PhoneNumber&LookUpValue
[Route("MyLookupMethod/GetForIVR")]
public Book Get(int LookupType, int LookUpValue) { ... }
}

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;}
}

MVC 4 is overwriting specific Action-Parameters

MVC 4 does present me some strange behaviour at the moment.
Imagine the following Code:
TestController.cs
public class TestController : Controller
{
public ActionResult Index(Function function, string action)
{
return View();
}
public class Function
{
public string Action { get; set; }
}
}
It seems, that when I call the URL directly through the browser (localhost:PORT/Test), the Action-Property gets automatically filled with "Index".
If the Action would be named "MySuperDuperActionWhichGetsInvokedQuiteOften", exactly this Methodname would be in the property.
Can somebody explain what MVC is doing here?
The Problem is, that I of course want to fill that stuff myself, for example through an AJAX-Query. But if MVC is filling in this property all by itself, this breaks some behaviour.
I could, of course, just rename my property and it would be working, but it would still be quite interesting what's going on.
EDIT
I would understand it that my second parameter, string action, get's filled with the method-name. But why on earth would MVC bind any property/parameter that is named the same to the request-value of it?
It is problem with default model binder. It "maps" request fields to properties in your class. There is an article of MSDN describing how does it works but to simply this situation the code will be like this:
Action = Request["action"] //where of course Request["action"] equals to name of your action