WebApi: Get api/Record/id/Tags - asp.net

In my ASP.NET MVC (6) web Web Api I have
[Produces("application/json")]
[Route("api/Record")]
public class RecordController : Controller
{
// ...
// GET: api/Record/5
[HttpGet("{id}", Name = "GetRecord")]
public async Task<Record> Get(string id)
{
var record = await repository.GetAsync<Record>(id);
return record;
}
Now, my Record contains some Tags.
I would like to return these tags via api/Record/5/Tags
How should I write my action in that case?

Assuming it is a property on the record create a route template to match the desired route and return the tags when called
[HttpGet("{id}/Tags")] // GET: api/Record/5/Tags
public async Task<IActionResult> GetTags(string id) {
var record = await repository.GetAsync<Record>(id);
if(record == null) return NotFound();
return Ok(record.Tags);
}

Related

How to check something before execute http request aspnet core web api 6

My customer want to validate token from query param like this
http://localhost/api/v1/users?token=xxxx
I can do like this:
[CustomAuthorize(Authorities = new[] { Constants.RoleGuest })]
[HTTPGet]
public async Task<IActionResult> Get(string token){
//call validate token function with token provided
//do something
}
Is there a way to implement automatic token authentication that does this for all requests except login and register?
It sucks to have to call the authentication function on every http request. Is this implementable as a custom attribute ?
This question don't mention how to implement authen and authorization. Main popurse is check something when user request to any endpoint. In this situation, it is token. It isn't same access token and refresh token
Thanks for all the help!
You can use action filter and custom attribute to implement it.
public class MyAuth : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
var actionInfo = context.ActionDescriptor as ControllerActionDescriptor;
var token = context.HttpContext.Request.Query.ContainsKey("token")
? Convert.ToString(context.HttpContext.Request.Query["token"])
: string.Empty;
var shouldStop = !IsValidToken(token, actionInfo);
if (shouldStop)
{
context.Result = new UnauthorizedResult();
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
private bool IsValidToken(string token, ControllerActionDescriptor actionInfo)
{
var valid = false;
var controllerName = actionInfo?.ControllerName;
var actionName = actionInfo?.ActionName;
var roles =
(actionInfo?.MethodInfo.GetCustomAttributes(typeof(CustomAuthorize), true)?.FirstOrDefault() as
CustomAuthorize).Roles;
// your token validation logic goes here
return valid;
}
}
public class CustomAuthorize : Attribute
{
public string[] Roles { get; }
public CustomAuthorize(string[] roles)
{
Roles = roles;
}
}
And in the program.cs you can register the Action filter as below
builder.Services.AddControllers(_ =>
{
_.Filters.Add(typeof(MyAuth));
});
Finally, your action method would look like below -
[CustomAuthorize(new string[]{Constants.RoleGuest})]
[HTTPGet]
public async Task<IActionResult> Get(){
// do actual work.
// this method will be only called if your validation logic pass.
}

asp-route-id always pass id as query parmeter

I'm trying pass id as route parameter by asp-route-id always pass as a query parameter
and I don't want to use href
<a asp-area="Employe" asp-controller="PersonManager" asp-action="UserDetails" asp-route-id="#Model.Provider.Id">details</a>
the route is like this
https://localhost:5002/Employe/PersonManager/UserDetails?id=b4065ff6-c7bd-4244-a6b6-9bc6b7b4c7a8
but I want be like this
https://localhost:5002/Employe/PersonManager/UserDetails/b4065ff6-c7bd-4244-a6b6-9bc6b7b4c7a8
and this is my action
[HttpGet]
public async Task<IActionResult> UserDetails([FromRoute] Guid id)
{
var user = await _service.GetOneUser(id);
return View(user);
}
and I don't want change fromRoute to fromQuery it must be FromRoute
To use the Id as part of the route, you need to define it as part of the HttpGet attribute.
[HttpGet("UserDetails/{id}")]
public async Task<IActionResult> UserDetails([FromRoute] Guid id)
{
var user = await _service.GetOneUser(id);
return View(user);
}
Define the route for HttpGet:
[HttpGet("UserDetails/{id}")]
public async Task<IActionResult> UserDetails([FromRoute] Guid id)
{
var user = await _service.GetOneUser(id);
return View(user);
}

Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>.Model.get returned null during Page Load

My ViewClass controller has a method that fetches the data from a Web API based on Id and ClassName. Now during "page-load" in my model pop-up, I want to display a video using #Model.ClassVideoUrl but I get an error instead.
public async Task<IActionResult> IndexAsync(string Id, string ClassName)
{
await ViewMyClass(rowId,section);
return View();
}
private async Task<bool> ViewMyClass(string Id,string ClassName)
{
//My Code executes fine all data fetch
return true;
}
My .cshtml view:
$(document).ready(function () {
$('#videoDialog').modal('show');
var video = document.getElementById('myLectVideo');
video.src = '#Model.ClassVideoUrl';
video.play();
});
How can I display the video in my model pop-up?
Solution
public async Task<IActionResult> IndexAsync(int rowId, string section)
{
// Fetch Data
return View(videoInfo);
}

How to OData Patch

I have a .net core 3.1 WEB Api service where I use OData (V4)
I have an endpoint where every query through GET METHOD is working fine, and with the same endpoint I can use POST METHOD and insert new records to database.
The problem is, the DELETE and PATCH METHODs are not working (or maybe they are, but if I try to use update or delete I always get a 404 Not Found error). I try to call them ( DELETE, PATCH) from POSTMAN, but I get the same 404 error, however the methods are in the controller.
MyController:
[ApiController]
[Route("[controller]")]
public class UsersController : ODataController
{
[HttpGet]
[EnableQuery()]
public IEnumerable<User> Get()
{
return new Context().Userek;
}
[HttpPatch]
[EnableQuery]
public async Task<IActionResult> Patch([FromODataUri] int id, Delta<User> user)
{
var ctx = new Context();
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await ctx.Userek.FindAsync(id);
if (entity == null)
{
return NotFound();
}
user.Patch(entity);
try
{
await ctx.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (id != 23)
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
public async Task<IActionResult> Delete([FromODataUri] int id)
{
var ctx = new Context();
var user = await ctx.Userek.FindAsync(id);
if (user == null)
{
return NotFound();
}
ctx.Userek.Remove(user);
await ctx.SaveChangesAsync();
return StatusCode(404);
}
}
Thank you for any help!

How to create ASP .NET MVC4 Web API to search my multiple parameters

How to create ASP.NET MVC4 json Web API
which allows to search products by id, barcode, search term or retrieve
all products since date ?
I tried to use ASP.NET MVC4 controller below.
Calling
http://localhost:52216/admin/api/Products/GetSince?since=2014-03-16%2021:47:29&_=1395007124964
returns error
Multiple actions were found that match the request:
System.Net.Http.HttpResponseMessage GetSince(System.String) on type MyApp.Controllers.ProductsController\r\n
System.Net.Http.HttpResponseMessage GetId(System.String) on type MyApp.Controllers.ProductsController"
How to fix this ?
This code looks ugly, it contains number of similar methods.
Which is best way to create such API ?
How to improve this code ?
Http GET method should used but method names and signatures can changed.
ASP.NET/Mono MVC4, jquery, jquery UI are used. Windows 2003 server should also supported, so .NET 4.5 or MVC5 cannot used.
public class ProductsController : ApiController
{
[HttpGet]
public HttpResponseMessage GetSince([FromUri]string since))
{
var toodelist = GetProducts(since, null, null, null);
return Request.CreateResponse(HttpStatusCode.OK,
new { products = toodelist.ToArray() });
}
[HttpGet]
public HttpResponseMessage GetId([FromUri]string id)
{
var toodelist = GetProducts(null, null, id, null);
return Request.CreateResponse(HttpStatusCode.OK,
new { products = toodelist.ToArray() });
}
[HttpGet]
public HttpResponseMessage GetBarcode([FromUri]string barcode)
{
var toodelist = GetProducts(null, barcode, null, null);
return Request.CreateResponse(HttpStatusCode.OK,
new { products = toodelist.ToArray() });
}
[HttpGet]
public HttpResponseMessage GetTerm([FromUri]string term)
{
var toodelist = GetProducts(null, null, null, term);
return Request.CreateResponse(HttpStatusCode.OK,
new { products = toodelist.ToArray() });
}
static List<Product> GetProducts(string since, string barcode, string id, string term)
{
... retrieves list of product from database using specified search criteria
if not null
}
}
How about using a search criteria DTO like this?
public class SearchCriteria
{
public int? Id { get; set; }
public DateTime? Since { get; set; }
// Other properties
}
Action method will be like this.
public class ProductsController : ApiController
{
public HttpResponseMessage GetProducts([FromUri]SearchCriteria crit))
{
// Validate and clean crit object
var list = GetProducts(crit);
// return list
}
}
GetProducts can return the list of products based on the properties set in SearchCriteria object. If a query string field is not present, corresponding property will be null.

Resources