My goal is to have a controller with method
I am trying to create an attribute DefaultValue as below:
class ModelClass
{
int modelId;
string modelName;
[DefaultValue("foo")]
string modelString;
}
class ModelClass2
{
string fooBar;
[DefaultValue("bar")]
string otherStringValue;
}
with controller:
[HttpPut]
public async Task<HttpResponseMessage> Put(ModelClass model)
{
...
}
[HttpPost]
public async Task<HttpResponseMessage> Put(ModelClass2 model2)
{
...
}
The way this DefaultValue will work is that when a user passes a value in, if modelString in ModelClass is null or the empty string, this will populate it with "foo" (from the constructor of the attribute).
Else, the user defined value will be used.
The same would be true of otherStringValue in ModelClass2
In ASP.NET MVC it looks like this can be accomplished by using the BindProperty method of a IModelBinder interface, but I can't find anything similar for WebApi
Related
Detail: I am trying to set up a simple get/post method inside asp.net controller and using postman to set if its set up correctly. I have looked for similar question on stackoverflow and they did not fixed my issue
Error: My Get method works fine but my post method giving an following error. Please see below postman:
debug: if I add a break line inside post method. it is never reaching to that break line
Code in asp.net
[ApiController]
[Route("[controller]")]
public class CoursesTakenController : Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] {"value", "value" }
}
[HttpPost]
public Task<ActionResult<string>> Post([FromBody] string values)
{
return Ok(values);
}
}
I also tried this: but doesnt work
[HttpPost]
public async Task<IActionResult> Post([FromBody] string values)
{
return Ok();
}
You are posting a json object while the method expects a string. System.Text.Json (default json serializer used by ASP.NET Core) is pretty restrictive in JsonTokenType handling, so either post a string i.e. just "RandomText" (or encoded into string json object - {\"values\":\"asdasdasd\"}) or change action to accept an object:
public class Tmp
{
public required string Values { get; set; }
}
[HttpPost]
public async Task<ActionResult<string>> Post([FromBody] Tmp values)
{
...
}
I have the following code
public class BooksController : Controller
{
[Route("/Books/{id?}")]
public IActionResult Index(string id)
{
return View(id);
}
}
My problem is that when I try to enter the parameter it is (as it seems) considered as controller's action so I keep getting this exception.
I need somebody to explain what am I doing wrong.
If you want to pass some parameter to a view as a string you can make this like below:
public class BooksController : Controller
{
[Route("/Books/{id?}")]
public IActionResult Index(string id)
{
if (string.IsNullOrEmpty(id))
id = "default_value";
return View((object)id);
}
}
If the string type is passing to the View() call without casting to object it will be interpreted as a view name.
And the view model data should be declared as
#model string;
<h2>#Model</h2>
Try changing the route as given below -
[Route("Books", Name = "id")]
I am coming from a heavy Java/Spring background and trying to transition some knowledge over to ASP.NET Core 6.
In Spring, on a RestController, I am able to route the request based on the presence of a query parameter.
So a HttpRequest with the uri: /students?firstName=Kevin can be routed to a different controller method than a HttpRequest with the uri: /students.
In ASP.NET Core 6, I am unable to determine if the equivalent is possible after working through some examples and reading the documentation for Web API.
Here is what I am trying to achieve, is this possible using two methods and routing configuration that will discern which controller method to invoke based on the query parameter?
[ApiController]
[Route("Students")]
public class StudentHomeProfileController : ControllerBase
{
[HttpGet] //Route here when no parameters provided
public async Task<ActionResult<IEnumerable<Student>>> GetStudentAsync()
{
/* Code omitted */
}
[HttpGet] //Route here when firstName query param provided
public async Task<ActionResult<IEnumerable<Student>>> SearchStudentAsync([FromQuery] string firstName)
{
/* Code omitted */
}
}
While filtering by query parameters does not come with ASP.NET Core out of the box, it's not too hard to supply this functionality on your own.
When it comes to extensibility, ASP.NET has some superpowers, one of them is IActionConstraint, which
Supports conditional logic to determine whether or not an associated action is valid to be selected for the given request. (Source)
Creating an annotation to filter for query parameters is as easy as
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class QueryParameterConstraintAttribute : Attribute, IActionConstraint
{
private readonly string _parameterName;
public QueryParameterConstraintAttribute(string parameterName)
{
this._parameterName = parameterName;
}
public bool Accept(ActionConstraintContext context)
{
return context.RouteContext.HttpContext.Request.Query.Keys.Contains(this._parameterName);
}
public int Order { get; }
}
All that's left is annotating your controller method with that constraint
[HttpGet] //Route here when firstName query param provided
[QueryParameterConstraint("firstName")]
public async Task<ActionResult<IEnumerable<Student>>> SearchStudentAsync([FromQuery] string firstName)
{
/* Code omitted */
}
In a quick test I was able to confirm that it seems to work as intended, even if you add multiple of those attributes for different query parameters (if all conditions match, the route is called).
(Please note, this was tested with .NET Core 2.1. Anyway, it shuold be pretty much the same with .NET 6)
I think you are looking for something like this, you need to specify the parameter in the "HttpGet" attribute
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-6.0#attribute-routing-with-http-verb-attributes
[Route("api/[controller]")]
[ApiController]
public class Test2Controller : ControllerBase
{
[HttpGet] // GET /api/test2
public IActionResult ListProducts()
{
return ControllerContext.MyDisplayRouteInfo();
}
[HttpGet("{id}")] // GET /api/test2/xyz
public IActionResult GetProduct(string id)
{
return ControllerContext.MyDisplayRouteInfo(id);
}
[HttpGet("int/{id:int}")] // GET /api/test2/int/3
public IActionResult GetIntProduct(int id)
{
return ControllerContext.MyDisplayRouteInfo(id);
}
[HttpGet("int2/{id}")] // GET /api/test2/int2/3
public IActionResult GetInt2Product(int id)
{
return ControllerContext.MyDisplayRouteInfo(id);
}
}
You are trying to differentiate API calls using query params. this is not the way to do this. if you want to separate the calls you should probably use path params instead.
Read more about Routing in ASP.NET Core - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-6.0
I tried to call the update web api on Postman but it seems that it doesn't pass the id param to the asp.net core controller (asp.net core 2.0)
public class ShoppingCartController : BaseController
{
[HttpPut("{id}")]
[Route("api/ShoppingCart/UpdateShoppingCartItem")]
public IActionResult UpdateShoppingCartItem(long id)
{
return new NoContentResult();
}
}
You have to use [FromBody].
[HttpPut("{id}")]
[Route("api/ShoppingCart/UpdateShoppingCartItem")]
public IActionResult UpdateShoppingCartItem([FromBody]long id)
{
return new NoContentResult();
}
In Postman you must use a simple number.
Replace:
{
"id":87908908
}
with
87908908
Default behaviour of param parsing: From Url.
Use [FromBody] before your method param to let asp parse this param from the Body.
Can you try changing method UpdateShoppingCartItem to the following:
public IActionResult UpdateShoppingCartItem([FromBody] long id)
HttpPut now accepts the route as parameter, so you can combine your attributes.
public class ShoppingCartController : BaseController
{
[HttpPut("api/ShoppingCart/UpdateShoppingCartItem")]
public IActionResult UpdateShoppingCartItem(long id)
{
return new NoContentResult();
}
}
The model binder should infer the value of id from the body.
Using [HttpPut("{id}")] would mean that a put request to localhost:44342/65465 would be a valid action.
I'm trying to get the parameters of specific attribute routed URL on ActionFilterAttribute. For instance I have an action like below:
[Route("/v1/test/{userId}/{udid}")]
public object GetNewObject(int userId, string udid)
And in action filter attribute the absolute url is coming something like "http://test.example.com/v1/test/1/123-asda-231-asd". However I want to parse these parameters as userId=1 and udid=... within a collection.
Is it possible?
Anyway I found the answer,
Within RouteData of ControllerContext we may able to retrieve the specified value.
actionContext.ControllerContext.RouteData.Values["udid"]
[Route("...")] is possible only in MVC 5.
I think you want to do something like this
[RoutePrefix("api/users")]
public class UsersController : ApiController
{
// GET api/users
[Route("")]
public IEnumerable<User> Get() { ... }
// GET api/user/5
[Route("{id:int}")]
public Book Get(int id) { ... }
// POST api/users
[Route("")]
public HttpResponseMessage Post(User book) { ... }
}
where each User contains your properties
public class User
{
int UserId{get;set;}
string Udid{get; set;}
}