how to return an exception from async in asp.net webapi - asp.net-web-api

I have a WebAPI2 mvc app where I'm doing Get/Post to another api. My code looks like below
public Task<SomeEntity> AddAsync(SomeEntity someEntity)
{
try
{
var response = apiService.PostItem(url, someEntity);
if (response == null || response!="Successful")
{
throw new InvalidOperationException(response);
}
}
catch (Exception ex)
{
_logger.Error("Error " + ex.Message);
// how to return this error or exception;
}
return Task.FromResult(someEntity);
}
If the call to the internal api return an exception string then I need to forward it from this method call. Any ideas how can I do it? thanks

You can use IHttpActionResult or HttpResponseMessage as your return type and return proper HTTP-Status codes. In case of exception you can return [if you return IHttpActionResult ]
public IHttpActionResult Error()
{
var error = new HttpError();
return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.BadRequest, error));
}
or as in your example, throw HttpResponseException with appropriate status code.
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var message = string.Format("Product with id = {0} not found", id);
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
}
else
{
return item;
}
}

Related

How to define dependencies on two client calls in quarkus reactive programming

I have two Client APIs that return an Uni.
Uni<Customer> getCustomer(customerID)
Uni<Address> getAddress(addressID)
And I want to open a REST API
Uni<FullCustomer> getFullCustomer(String customerID)
The logic is to make the Customer Client call first. If the returned customer object has addressID then make the second Address Client call and get shipping address details. If shipping address is not available then just wrap the customer in FullCustomer object and return else wrap both customer and address in FullCustomer object and return.
I dont want to block the thread on client call (await().indefinitely()), hence i am using onItem and transfer method call. But my code returns a Uni<Uni> and i want it to return a Uni.
#GET
#Path("api/customer/{id}")
#Produces({ "application/json" })
Uni<Uni<FullCustomer>> getFullCustomer(#PathParam("id") String customerID){
Uni<Customer> customerResponse = getCustomer(customerID);
Uni<Uni<FullCustomer>> asyncResponse = customerResponse.onItem().transform(customer -> {
if (customer.getAddressId() != null) {
Uni<Address> addressResponse = getAddress(customer.getAddressId());
Uni<FullCustomer> fullCustomer = addressResponse.onItem().transform(address -> {
if (address.getShippingAddress() != null) {
return new FullCustomer(customer, address.getShippingAddress());
} else {
return new FullCustomer(customer);
}
});
}
return Uni.createFrom().item(new FullCustomer(customer));
});
return asyncResponse;
}
How can I rewrite my code so that it returns Uni keeping reactive ( async client ) calls
Got the solution. Thanks Ladicek for comments.
public Uni<FullCustomer> getFullCustomer(#PathParam("id") String customerID) {
return getCustomer(customerID)
.onItem()
.transformToUni(customer -> {
if (customer.getAddressId() != null) {
return getAddress(customer.getAddressId()).onItem().transform(address -> {
if (address.getShippingAddress() != null) {
return new FullCustomer(customer, address.getShippingAddress());
} else {
return new FullCustomer(customer);
}
});
} else {
return Uni.createFrom().item(new FullCustomer(customer));
}
});
}

Can I catch specific exceptions globally in a Razor Page (all handler methods) and include them in ModelState?

I'd like to allow all handler methods in a Razor Page to be wrapped by some sort of logic to handle specific exceptions that are more or less validation exceptions.
I've tried the following, but still get the developer exception page:
public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
try
{
await next();
}
catch(NotImplementedException ex)
{
_logger.LogWarning(ex, ex.Message);
ModelState.AddModelError(string.Empty, "Oops... this isn't all done yet.");
context.Result = Page();
}
catch (DomainValidationException ex)
{
ModelState.Include(ex.Results);
context.Result = Page();
}
}
The exception does not appear to bubble up from the await next() call and is handled in aspnetcore somehow.
It turns out that the next returns a result that needs to be inspected to get the exception and return the result.
The final implementation looks something like this:
public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
var result = await next();
if (result.Exception != null)
{
if (result.Exception is NotImplementedException nex)
{
result.ExceptionHandled = true;
_logger.LogWarning(nex, nex.Message);
ModelState.AddModelError(string.Empty, "Oops... this isn't all done yet.");
}
else if (result.Exception is DomainValidationException dex)
{
result.ExceptionHandled = true;
ModelState.Include(dex.Results);
}
if (result.ExceptionHandled)
{
result.Result = Page();
}
}
}

Get HttpHeaders from HttpRequestException?

I have a Web API, When the incoming request is not valid then the API sends back a HttpStatusCode.BadRequest and API would also add a CorrelationId into Response's HttpHeader. Something like below
public class ValidateRequestAttribute : ActionFilterAttribute
{
public ValidateRequestAttribute()
{
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid == false)
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.HttpContext.Response.Headers.Add("x-correlationid", "someid");
context.Result = new ContentResult()
{
Content = "bad request."
};
}
}
}
On client side im using HttpClient to access the API. I am not sure how client would retrieve HttpStatusCode and HttpHeader here. Here is my client code
public bool Process(url)
{
bool result = false;
try
{
Task.Run(async () => await _httpClient.GetStringAsync(url).ConfigureAwait(false)).Result;
}
catch (Exception ex)
{
if(ex is AggregateException)
{
var aggregateException = ex as AggregateException;
foreach(var innerException in aggregateException.InnerExceptions)
{
if (innerException is HttpRequestException)
{
var httpRequestException = innerException as HttpRequestException;
// how do i get StatusCode and HttpHeader values here??
}
}
}
}
return result;
}
I have already gone through SO post here and MSDN article here and also Stephen Cleary's article here
Even though its recommended to make async all the way down, I this case Client and API are both disconnected from each other and client is synchronous. Note that Client's Process method is synchronous method.
Like this:
public bool Process(string url)
{
var result = _httpClient.GetAsync(url).ConfigureAwait(false).GetAwaiter().GetResult();
if (result.StatusCode == HttpStatusCode.BadRequest)
{
IEnumerable<string> values;
if (result.Headers.TryGetValues("x-correlationid", out values))
{
// Should print out "someid"
Console.WriteLine(values.First());
}
}
return result.IsSuccessStatusCode;
}
Also note that doing .GetAwaiter().GetResult(); vs .Result; is recommended since it makes the code easier to work with because it does not throw an AggregateException.
If you want to read the response content as a string just do:
var content = result.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
If you want to make your code async though you should use the async/await keyword and skip the .GetAwaiter().GetResult();.

How to fix this exception type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in

This is continuation to my question: [How to get name data of multiple json object list that will be posted to web api?
I was able to update my code but now I am getting an erexception on
if (db.Sales1.Any(sl => sl.ExtSerial != s.ExtSerial))
Exception goes: An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
Additional information: The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
Here is the code:
public HttpResponseMessage PostSales(List<Sales> Sales, [FromUri] string auth)
{
try
{
if (ModelState.IsValid)
{
if (auth == "KDI")
{
#region Stable but not multiline
//Int64 rs = db.Sales1.Where(sl => sl.Serial == Sales.Serial).Count();
//if (1 == rs)
//{
// return Request.CreateErrorResponse(HttpStatusCode.Conflict, " Duplicate Found!");
//}
//else
//{
// db.Sales1.Add(Sales);
// db.SaveChanges();
// return Request.CreateErrorResponse(HttpStatusCode.OK, "Added!");
//}
#endregion
Parallel.ForEach(Sales, s =>
{
if (db.Sales1.Any(sl => sl.ExtSerial != s.ExtSerial))
{
db.Sales1.Add(s);
db.SaveChanges();
}
else
{
return;
}
});
return Request.CreateErrorResponse(HttpStatusCode.OK, "Success!");
}
else
{
return Request.CreateResponse(HttpStatusCode.Unauthorized, "Unauthorized Access!");
}
}
else
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Something's wrong with the JSON model you sent me.");
}
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}

Xamarin http webservice issue

I m trying to use http request webservice issue is that when we post wrong username and password the login service generate exception and it can't return any value in async calls.
A code snippet would help assist with the problem ...
However using a try catch should help you catch your exception and prevent application from crashing and handling the exceptions accordingly.
As seen in my sample code below I cater for the incorrect details entered / connectivity problems. I peform the http async request then parse the xml to my model handling the exceptions accordingly
var response = await WebRequestHelper.MakeAsyncRequest(url, content);
if (response.IsSuccessStatusCode == true)
{
Debug.WriteLine("Login Successfull" + "result.IsSuccessStatusCode" + response.IsSuccessStatusCode);
var result = response.Content.ReadAsStringAsync().Result;
result = result.Replace("<xml>", "<LoginResult>").Replace("</xml>", "</LoginResult>");
loginResult = XMLHelper.FromXml<LoginResult>(result);
if (loginResult != null)
{
login.Type = ResultType.OK;
login.Result = loginResult;
}
else
{
login.Type = ResultType.WrongDetails;
}
}
else
{
Debug.WriteLine("Login Failed" + "result.IsSuccessStatusCode" + response.IsSuccessStatusCode);
login.Type = ResultType.WrongDetails;
}
}
catch (Exception ex)
{
login.Type = ResultType.ConnectivityProblem;
}
Web Request
public static async Task<HttpResponseMessage> MakeAsyncRequest(string url, Dictionary<string, string> content)
{
var httpClient = new HttpClient();
httpClient.Timeout = new TimeSpan(0, 5, 0);
httpClient.BaseAddress = new Uri(url);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type: application/x-www-form-urlencoded", "application/json");
if (content == null)
{
content = new Dictionary<string, string>();
}
var encodedContent = new FormUrlEncodedContent(content);
var result = await httpClient.PostAsync(httpClient.BaseAddress, encodedContent);
return result;
I would recommend wrapping the response in a generic ServiceResponse where you can store the exceptions. await methods can be included in try/catch blocks so the standard process can be followed.
E.G.
public async Task<ServiceResponse<T>> PostAsync<T>(String address, object dto){
var content = Serializer.SerializeObject (dto);
var response = await client.PostAsync (
address,
new StringContent (content));
if (response.IsSuccessStatusCode) {
try {
var responseString = await response.Content.ReadAsStringAsync ();
return new ServiceResponse<T> (Serializer.DeserializeObject<T> (responseString),
response.StatusCode);
} catch (Exception ex) {
return new ServiceResponse<T> (response.StatusCode, ex);
}
} else {
return new ServiceResponse<T> (response.StatusCode);
}
}
With the ServiceResponse defined as :
public class ServiceResponse<T>
{
public HttpStatusCode StatusCode { get; set;}
public T Value { get; set;}
public String Content { get; set;}
public Exception Error {get;set;}
public ServiceResponse(T value, HttpStatusCode httpStatusCode){
this.Value = value;
this.StatusCode = httpStatusCode;
}
public ServiceResponse(HttpStatusCode httpStatusCode, Exception error = null){
this.StatusCode = httpStatusCode;
this.Error = error;
}
}
This will give you a clean way of managing all your HTTP responses and any errors that may occur.

Resources