Sometime I allow to create/update the status of IoT devices using the raw data. It means that the client can read the device device state as an array of bytes and send that data via API. The data parsed by the server and send back as a regular DTO.
For create I might introduce the following CreateStatusFromRawData
method:
[HttpGet("{id}/status")]
[ProducesResponseType(200, Type = typeof(DeviceStatus))]
[ProducesResponseType(404)]
public async Task<IActionResult> GetStatus(Guid id)
{
// gets the device status
}
[HttpPost("{id}/status/rawdata")]
[ProducesResponseType(201, Type = typeof(DeviceStatus))]
[ProducesResponseType(404)]
public async Task<IActionResult> CreateStatusFromRawData(Guid id, [FromBody]byte[] rawdata)
{
// some parsing logic
return CreatedAtAction(nameof(GetStatus), new {id})
}
I would like to make the same for update operation:
[HttpPut("{id}/status/rawdata")]
[ProducesResponseType(200, Type = typeof(DeviceStatus))]
[ProducesResponseType(404)]
public async Task<IActionResult> UpdateStatusFromRawData(Guid id, [FromBody]byte[] rawdata)
{
// some parsing logic
return **UpdatedAtAction**(nameof(GetStatus), new {id})
}
How might UpdatedAtAction method implementation look like? So I want actually 3 things:
You could implement your own UpdatedAtAction
like CreatedAtAction.
UpdatedAtActionResult
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
using System;
namespace MVCPro.CustomResult
{
public class UpdatedAtActionResult : ObjectResult
{
private const int DefaultStatusCode = StatusCodes.Status200OK;
public UpdatedAtActionResult(
string actionName,
string controllerName,
object routeValues,
object value)
: base(value)
{
ActionName = actionName;
ControllerName = controllerName;
RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
StatusCode = DefaultStatusCode;
}
/// <summary>
/// Gets or sets the <see cref="IUrlHelper" /> used to generate URLs.
/// </summary>
public IUrlHelper UrlHelper { get; set; }
/// <summary>
/// Gets or sets the name of the action to use for generating the URL.
/// </summary>
public string ActionName { get; set; }
/// <summary>
/// Gets or sets the name of the controller to use for generating the URL.
/// </summary>
public string ControllerName { get; set; }
/// <summary>
/// Gets or sets the route data to use for generating the URL.
/// </summary>
public RouteValueDictionary RouteValues { get; set; }
/// <inheritdoc />
public override void OnFormatting(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
base.OnFormatting(context);
var request = context.HttpContext.Request;
var urlHelper = UrlHelper;
if (urlHelper == null)
{
var services = context.HttpContext.RequestServices;
urlHelper = services.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
}
var url = urlHelper.Action(
ActionName,
ControllerName,
RouteValues,
request.Scheme,
request.Host.ToUriComponent());
if (string.IsNullOrEmpty(url))
{
throw new InvalidOperationException("NoRoutesMatched");
}
context.HttpContext.Response.Headers[HeaderNames.Location] = url;
}
}
}
MyControllerBase
public class MyControllerBase: Controller
{
[NonAction]
public virtual UpdatedAtActionResult UpdatedAtAction(string actionName, object value)
=> UpdatedAtAction(actionName, routeValues: null, value: value);
[NonAction]
public virtual UpdatedAtActionResult UpdatedAtAction(string actionName, object routeValues, object value)
=> UpdatedAtAction(actionName, controllerName: null, routeValues: routeValues, value: value);
[NonAction]
public virtual UpdatedAtActionResult UpdatedAtAction(
string actionName,
string controllerName,
object routeValues,
object value)
=> new UpdatedAtActionResult(actionName, controllerName, routeValues, value);
}
Useage
[Route("api/User")]
public class UserApiController : MyControllerBase
{
[HttpGet("{id}/status")]
[ProducesResponseType(200, Type = typeof(DeviceStatus))]
[ProducesResponseType(404)]
public async Task<IActionResult> GetStatus(Guid id)
{
// gets the device status
return Ok(new DeviceStatus { DeviceId = id });
}
[HttpPost("{id}/status/rawdata")]
[ProducesResponseType(201, Type = typeof(DeviceStatus))]
[ProducesResponseType(404)]
public async Task<IActionResult> CreateStatusFromRawData(Guid id, [FromBody]byte[] rawdata)
{
// some parsing logic
return CreatedAtAction(nameof(GetStatus), new { id });
}
[HttpPut("{id}/status/rawdata")]
[ProducesResponseType(200, Type = typeof(DeviceStatus))]
[ProducesResponseType(404)]
public async Task<IActionResult> UpdateStatusFromRawData(Guid id, [FromBody]byte[] rawdata)
{
// some parsing logic
return UpdatedAtAction(nameof(GetStatus), new { id });
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With