I am working on a web api where I need to validate response returned. I want to write some generic code to ensure that response returned from api is in a correct format.
Basically there are fields like status, remarks etc which should be present in response if these are null or invalid then i should return some error code but not sure how to achieve this, can someone guide me here? Thanks in advance.
Thanks,
Sudama
The following might work for you. It assumes you're using an ObjectResult though you can adapt it to the IActionResult implementation that you're actually using. The following is not production code; rather, it gives a sense of what you could do.
public class MyResultFilter : IResultFilter
{
public void OnResultExecuted(ResultExecutedContext context)
{
}
public void OnResultExecuting(ResultExecutingContext context)
{
var result = context.Result as ObjectResult;
var value = result.Value as MyCustomType;
if (!IsValid(value)
{
context.Result = new StatusCodeResult(500);
}
}
private bool IsValid(MyCustomType value)
{
return value != null &&
value.Status != null &&
value.Remarks != null;
}
}
Related
When I click on an AjaxLink, I would like to have a validation via JavaScript on the client side first (because the LocalStorage is queried) and then depending on the result, further JavaScript calls are made. How can i achieve this?
In a pseudo code it would look like this:
new AjaxLink<>("myId", myModel) {
#Override
public void onClick(AjaxRequestTarget target) {
boolean isCounterValid = target.appendJavaScript(checkCounter()); // i know that this is not possible, therefore pseudo code
if(isCounterValid) {
target.appendJavaScript(someOtherJavaScript());
}
else {
target.appendJavaScript(anotherJavaScript());
}
}
private String checkCounter() {
return "var count = window.localStorage.getItem('myCounter'); return count !== 1;";
}
private String someOtherJavaScript() {
return "change something";
}
private String anotherJavaScript() {
return "change other thing";
}
};
You need to send extra request parameters with the Ajax call when the link is clicked. For that you should override updateAjaxAttributes(AjaxRequestAttributes attributes) method of AjaxLink:
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
{
attributes.getDynamicExtraParameters().add("var count = window.localStorage.getItem('myCounter'); return [{\"name\":\"count\", \"value\": count}]");
}
This way inside AjaxLink#onClick() you can read the count via:
int count = getRequest().getRequestParameters().getParameterValue("count").toInt();
AJAX components and behaviors can customize AJAX attributes overriding updateAjaxAttributes and using a custom implementation of AjaxCallListener which exposes different method to hook into the AJAX request cycle. In you case you could use AjaxCallListener#getBeforeSendHandler.
For a full introduction to this topic (with examples) see user guide:
https://ci.apache.org/projects/wicket/guide/8.x/single.html#_ajax_request_attributes_and_call_listeners
I have two Get methods. I want to access this by using following urls
https://localhost:44396/api/values/1
https://localhost:44396/api/values/1?status=1
But I am trying to call this I am getting following exception
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(SomeEnum id)
{
//somecode
return "value";
}
[HttpGet("{id}")]
public ActionResult<string> Get(SomeEnum id,int status)
{
//somecode
return "value";
}
Is there any way to use routs like this with mutltiple get methods
There is nothing out of the box provided by ASP.NET core to help your case. As suggested in one of the comments, you should make the status parameter as nullable and use it within the action method to decide what next to do. Something like this:
[HttpGet("{id}")]
public ActionResult<string> Get(SomeEnum id,int? status)
{
if(status == null)
{
//perform usual logic which requires only id
}
else
{
//perform logic or call a method which requires both id and status
}
return "value";
}
I have a web api to consume the data coming from android mobile. This web api will consume the multi part file from along with the form data the web api request. I followed this article to archive.
[CustAuthAsync]
public async Task<HttpResponseMessage> SaveEHSInspectionData()
{
try
{
string root = HttpContext.Current.Server.MapPath("~/App_Data");
MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(root);
//do stuff
var res = await Request.Content.ReadAsMultipartAsync(provider);
// DO SOME STUFF
}
catch (Exception exp)
{
}
return Request.CreateResponse(HttpStatusCode.OK, result);
}
I wanted to do the custom access validation for this web api, so implemented a filter to validate the request.
I have the filter like below
public class CustAuthAsyncAttribute : ActionFilterAttribute
{
public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
InternalOnExecutingAsync(actionContext);
}
}
The internal method like this
protected void InternalOnExecutingAsync(HttpActionContext actionContext)
{
var authValue = actionContext.Request.Headers;
if (authValue.Contains("CustomAccessToken"))
{
string token = authValue.GetValues("CustomAccessToken").First();
var result = // doing some decription
if (result != null)
{
bool validationResult = // validation with database
if (!validationResult)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{ ReasonPhrase = "Invalid token" };
}
}
else
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{ ReasonPhrase = "Invalid token" };
}
}
else
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{ ReasonPhrase = "Unauthorized Request" };
}
These implementations are working fine in API Client Tools (Example: Postman) if the validation passes, allows the request to the method.
Postman Response screen shot
This is not working in mobile app, Saying the response message as Unauthorized Access. and not allowing the request to the method even the custom access validations are passed.
FYI : This method is working fine in mobile without filter
Help me to get this works in mobile app also.
Thanks in advance.
Your using the wrong type of filter to manage access. You should use an authorization filter. Besides you can't have an async method to authorize. You have to make the calling client wait for clearance. This may cause the side effects you're experiencing.
I'm not sure this has any to do with fact that it's a mobile application, however the authorization phase ir prior to the processing of the request. Verify that your are not using any other form of authorization in your project.
You should implement an authorization filter by inheriting AuthorizeAttribute and overriding IsAuthorized(HttpActionContext actionContext) method:
public class CustAuthAsync : AuthorizeAttribute
{
public CustAuthAsync()
{
///Some initialization if required. Otherwise, not necessary to declare the constructor..
}
protected override bool IsAuthorized(HttpActionContext actionContext)
{
var authValue = actionContext.Request.Headers;
if (authValue.Contains("CustomAccessToken"))
{
string token = authValue.GetValues("CustomAccessToken").First();
var result = // doing some decription
if (result != null)
{
return //database validation
}
else
{
return false;
//No need to create special unauthorized response. You should not hint the reason at this point. You can do this in the HandleUnauthorizedRequest method.
}
}
else
{
return false;//No need to create special unauthorized response.
}
}
}
You can use this attribute to decorate your controllers. You can even pass parameter in the constructor for more granular control on access management, like a required role to access de controller.
I am totally new to Web API an am not understanding how to Filter get calls.
This method returns all items in my database.
// GET: api/LogEntries
public IQueryable<LogEntry> GetLogEntries()
{
return db.LogEntries;
}
This method returns a specific item in my database.
// GET: api/LogEntries/5
[ResponseType(typeof(LogEntry))]
public IHttpActionResult GetLogEntry(int id)
{
LogEntry logEntry = db.LogEntries.Find(id);
if (logEntry == null)
{
return NotFound();
}
return Ok(logEntry);
}
So now I want to filter the returned records so I created this method but it won't work because the specific item method gets called. I seem to be missing a concept and am hoping you can point me to more clear understanding. Thanks
// GET: api/LogEntries
public IQueryable<LogEntry> GetLogEntries(string levelID)
{
int levIdInt;
if (Int32.TryParse(levelID, out levIdInt))
{
return db.LogEntries.Take(300).Where(l => (int)l.Level == levIdInt).OrderByDescending(d => d.TimeStamp);
}
return db.LogEntries.Where(i => i.ID < 0);
}
You need to specify the route for that method
[Route("api/LogEntries/Level/{levelID}"]
public IQueryable<LogEntry> GetLogEntries(string levelID)
{}
More on routing is available here http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
I want to see if a record exists in DB. I'm checking for null/whitespace and then doing a string compare everywhere and I want to put in a function so I don't have to write the same code over and over.
Here's what the code looks like for each thing I'm comparing to...
return Db.AttributeNames.FirstOrDefault(an =>
(!string.IsNullOrWhiteSpace(an.Name) &&
string.Compare(attributeName.Name, an.Name, StringComparison.OrdinalIgnoreCase) == 0) &&
(!string.IsNullOrWhiteSpace(an.Namspace) &&
string.Compare(attributeName.Namespace, an.Namspace, StringComparison.OrdinalIgnoreCase) == 0));
I have tried something like this...it obviously isn't right.
public Class1 Get(string url)
{
return Db.Class1s.FirstOrDefault(f => Equal<Class1>(f.Value, url));
}
public static Expression<Func<T, bool>> Equal<T>(string input, string url)
{
return a => input == url; // just to test for now, I need to add null/ws check and do compare
}
I know, I know. I have no idea what I'm doing..but I would appreciate some help!
You will probably need to create an extension method:
public static class MyExtensions
{
public static bool UrlEqual(this Class1s obj, string url)
{
return obj.Value == url;
}
}
Then you can make the following call:
return Db.Class1s.FirstOrDefault(f => f.UrlEqual(url));