I am trying to create different types of errors in an ASP.NET controller (which communicates with a service). Right now I am focusing on a ServiceNotFound error, but DbContextMock() always returns true. What is the correct way to do this?
(In OrdersController.cs)
public OrdersController(IOrdersService ordersService)
{
_ordersService = ordersService ?? throw new ArgumentNullException(nameof(ordersService));
}
[HttpPut]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
public async Task<IActionResult> PutOrdersAsync()
{
try
{
await _ordersService.PutOrdersAsync();
return new StatusCodeResult(StatusCodes.Status204NoContent);
}
catch (ServiceException ex)
{
return StatusCode(
(int)ex.StatusCode,
Responses.ErrorResponse with { Message = ex.Message, Content = JsonConvert.SerializeObject(ex), RequestId = Request.HttpContext.Connection.Id }
);
}
catch (Exception ex)
{
return StatusCode(
StatusCodes.Status500InternalServerError,
Responses.ErrorResponse with { Message = ex.Message, Content = JsonConvert.SerializeObject(ex), RequestId = Request.HttpContext.Connection.Id }
);
}
}
(In Tests.cs)
...
var context = new DbContextMock();
...
var service = GetOrdersService(context.Object, _pdcClientFactory.Object);
...
await service.PutOrdersAsync();
Related
I encounter a very wierd error.
I have an Item with some properties that are JsonRequired.
When i try to call my route to get my Item when one property that is required is missing, my error is not automatically thrown as an error code 500 I get a 200 Ok instead.
Here is my route :
[HttpGet("{itemId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<Item>> GetItemByIdAsync(long installationId, Guid itemId)
{
return await _itemService.GetItemByIdAsync(installationId, itemId);
}
Here is my Item class :
public class Item
{
[JsonProperty("id")]
[JsonRequired]
public Guid Id { get; set; }
[JsonProperty("name")]
[JsonRequired]
public string Name { get; set; }
}
And here is my middleware :
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (NotFoundException ex)
{
await HandleExceptionAsync(context, HttpStatusCode.NotFound, ex);
}
catch (UnauthorizedException ex)
{
await HandleExceptionAsync(context, HttpStatusCode.Unauthorized, ex, false);
}
catch (ConflictException ex)
{
await HandleExceptionAsync(context, HttpStatusCode.Conflict, ex);
}
catch (BadRequestException ex)
{
await HandleExceptionAsync(context, HttpStatusCode.BadRequest, ex);
}
}
private Task HandleExceptionAsync(HttpContext context, HttpStatusCode httpCode, Exception exception, bool displayException = true)
{
_logger.LogError(exception, $"Exception catched in middleware: {exception.Message}.");
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)httpCode;
var payload = JsonConvert.SerializeObject(new ApiError(displayException ? exception.Message : string.Empty));
return context.Response.WriteAsync(payload);
}
What I have tried :
If I try to add this catch in the middleware
catch (Exception ex)
{
await HandleExceptionAsync(context, HttpStatusCode.InternalServerError, ex);
}
There is still the same result I don't get a 500 error.
I don't really understand why my response is not overrided to be a 500 error.
Do you have any idea ?
Thanks a lot.
Since you do not show your _itemService.GetItemByIdAsync.It works well when I test with below code which has an 500 error.
public async Task<ActionResult<Item>> GetItemByIdAsync()
{
string json = #"{
'id': '2f5135a7-977c-4b26-a4e2-74b9e374a75e',
'name': null,
}";
Item x = JsonConvert.DeserializeObject<Item>(json);//throw 500 error using your Item model
return x;
}
You could also use Required property for JsonProperty like
[JsonProperty("name", Required = Required.Always)] //could not be null
public string Name { get; set; }
The definition for it is:
//
// Summary:
// Indicating whether a property is required.
public enum Required
{
//
// Summary:
// The property is not required. The default state.
Default = 0,
//
// Summary:
// The property must be defined in JSON but can be a null value.
AllowNull = 1,
//
// Summary:
// The property must be defined in JSON and cannot be a null value.
Always = 2,
//
// Summary:
// The property is not required but it cannot be a null value.
DisallowNull = 3
}
I am using App Insights in my web api 2 project, which is being called form a React Front End.
When something wrong happens I would like to show the user a generic error like: Please contact the admin, and show them a Guid, or error number.
Then with that error number I could check in App Insights what the real exception was.
Is this possible?
My web api code is below
namespace LuloWebApi.Controllers
{
[Authorize]
public class ClientController : ApiController
{
[HttpGet]
public async Task<List<Client>> GetClients()
{
//var telemetry = new TelemetryClient();
//try
//{
var clientStore = CosmosStoreHolder.Instance.CosmosStoreClient;
return await clientStore.Query().ToListAsync();
//}
//catch (System.Exception ex)
//{
// telemetry.TrackException(ex);
//}
}
[HttpGet]
public async Task<IHttpActionResult> GetClient(string clientId)
{
var telemetry = new TelemetryClient();
try
{
var clientStore = CosmosStoreHolder.Instance.CosmosStoreClient;
var client = await clientStore.Query().FirstOrDefaultAsync(x => x.Id == clientId);
if (client == null)
{
return NotFound();
}
return Ok(client);
}
catch (System.Exception ex)
{
telemetry.TrackException(ex);
return BadRequest("Unknown error");
}
}
[HttpPut]
public async Task<IHttpActionResult> UpdateClient(string id,[FromBody]Client client)
{
var telemetry = new TelemetryClient();
try
{
var clientStore = CosmosStoreHolder.Instance.CosmosStoreClient;
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await clientStore.UpdateAsync(client);
return Ok(result);
}
catch (System.Exception ex)
{
telemetry.TrackException(ex);
return BadRequest("Unknown error");
}
}
[HttpPost]
public async Task<IHttpActionResult> AddCLient([FromBody]Client Client)
{
var telemetry = new TelemetryClient();
try
{
var clientStore = CosmosStoreHolder.Instance.CosmosStoreClient;
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var added = await clientStore.AddAsync(Client);
return StatusCode(HttpStatusCode.NoContent);
}
catch (System.Exception ex)
{
telemetry.TrackException(ex);
return BadRequest("Unknown error");
}
}
public async Task<IHttpActionResult> DeleteClient(string clientId)
{
var telemetry = new TelemetryClient();
try
{
var clientStore = CosmosStoreHolder.Instance.CosmosStoreClient;
await clientStore.RemoveByIdAsync(clientId);
return Ok(clientId);
}
catch (System.Exception ex)
{
telemetry.TrackException(ex);
return BadRequest("Unknown error");
}
}
}
}
Please correct me if I misunderstand you.
I think it's as easy as manually creating a guid, and add to the exception telemetry as well to the BadRequest().
try
{
//some code here
}
catch(Exception ex)
{
string guid = Guid.NewGuid().ToString();
Dictionary<string,string> dt = new Dictionary<string, string>();
dt.Add("my error number1", guid);
telemetryClient.TrackException(ex,dt);
return BadRequest("Unknown error:"+guid);
}
And when you get the guid, you can search the related error in azure portal:
I am using the nexmo api for .NET to send verification code to given phone which gives me the following error
The underlying connection was closed
My code is as follows
public bool PhoneVerfication(string PhoneNumber, long userId)
{
try
{
long? _cellPhone = Convert.ToInt64(PhoneNumber);
var _util = new utilMessageSender();
_util.SendVerificationCode(PhoneNumber);
return true;
}
catch (Exception ex)
{
return false;
}
}
public utilMessageSender()
{
client = new Client(creds: new Credentials
{
ApiKey = "********",
ApiSecret = "**************",
ApplicationId = "*********-****-****-****-***********",
ApplicationKey = "**************"
});
}
public void SendVerificationCode(string phoneNumber)
{
try
{
var result = client.NumberVerify.Verify(new NumberVerify.VerifyRequest
{
number = phoneNumber,
brand = "Offey-app"
});
RequestId = result.request_id;
}
catch (Exception ex)
{
throw ex;
}
}
I am using this API for the first time it worked very fine and sent verification code to different phone numbers but I don't know what happened as now it's not working.
I have numerous method which I call using jquery ajax.
In order to handle any errors in the fail method I use the following code;
public async Task<ActionResult> UpdateStockTransactionAsync(
string TransactionDate, string Quantity, string ProductId, string TabCount)
{
try
{
//my code goes here
}
catch (System.Web.Http.HttpResponseException ex)
{
var msg = ex.Response.Content.ReadAsStringAsync().Result;
var errorModel = JsonConvert.DeserializeObject<AcknowledgementModel>(msg);
return new HttpStatusCodeResult(500, errorModel.errormessage);
}
catch (Exception ex)
{
return new HttpStatusCodeResult(500, ex.Message);
}
}
I seem to be repeating this an awful lot throughout my code, is it possible to maybe pull this out to a filter attribute? if so how?
One option is to use the overridable method OnException available on Controller class.
protected override void OnException(ExceptionContext filterContext)
{
var exception = filterContext.Exception;
if (exception is System.Web.Http.HttpResponseException) // Catch HttpResponseException
{
var msg = ex.Response.Content.ReadAsStringAsync().Result;
var errorModel = JsonConvert.DeserializeObject<AcknowledgementModel>(msg);
filterContext.Result = new HttpStatusCodeResult(500, errorModel.errormessage);
}
else // catch (Exception ex)
{
filterContext.Result = new HttpStatusCodeResult(500, ex.Message);
}
base.OnException(filterContext);
}
You can redirect results with filterContext.Result
I am new to writing Unit Test in visual studio. In my web application i have following contents.
1> Interface
public interface IGettProxy
{
Task<List<CityDetails>> getCity();
Task<List<CountryDetails>> getCountry(int cityId);
}
2> Contracts (Implementation of Interface)
public async Task<List<CityDetails>> getCity()
{
try
{
_serviceUrl = String.Format("{0}/Search/getCityinfo", _serviceUrl);
string requestUri = _serviceUrl;
client = new HttpClient();
var response = await client.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
var Result = new JavaScriptSerializer().Deserialize<List<CityDetails>>(json);
return Result;
}
else
{
throw new Exception("Errorhandling message");
}
}
catch (Exception ex) { throw ex; }
}
public async Task<List<CountryDetails>> getCountry(int cityId)
{
try
{
_serviceUrl = String.Format("{0}/Search/getcountryinfo?cityId={1}", _serviceUrl, cityId);
string requestUri = _serviceUrl;
client = new HttpClient();
var response = await client.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
var Result = new JavaScriptSerializer().Deserialize<List<CountryDetails>>(json);
return Result;
}
else
{
throw new Exception("Errorhandling message");
}
}
catch (Exception ex) { throw ex; }
}
3> Controller
private IGettProxy igettProxy;
public GettController(IGettProxy gettProxy)
{
igettProxy = gettProxy;
}
/// <summary>
/// Invoked on Page Load
/// </summary>
/// <returns></returns>
public async Task<ActionResult> Getdet()
{
try
{
List<CityDetails> cityDetails = await igettProxy.getCity();
SearchModel viewModel = new SearchModel();
viewModel.cityDetail = cityDetails;
return View(viewModel);
}
catch (Exception ex) { throw ex; }
}
/// <summary>
/// Get Country list based on city information
/// </summary>
/// <param name="cityId"></param>
/// <returns></returns>
public async Task<JsonResult> getCountry (int cityId)
{
try
{
List<CountryDetails> CountryDetails = await iSearchProxy.getCountry(cityId);
return Json(CountryDetails,JsonRequestBehavior.AllowGet);
}
catch (Exception ex) { throw ex; }
}
I have different class libraries for data member.
For injection configuration i am using Unity method.
So in this view i have drop down to bind city, country values.
For this drop down binding i want to write unit test. Please help me with this detail. Thanks in advance.
My Test method
[TestMethod]
public void bookAppointment()
{
List<CityDetails> cityDetails = new List<CityDetails>();
cityDetails.Add(new CityDetails {ID=1,CityName="Delhi"});
// var mockproxy = new StubISearchProxy();
StubISearchProxy searchProxy = new StubISearchProxy();
searchProxy.GetCity = () => cityDetails;
SearchController searchController = new SearchController(searchProxy);
var str = searchController.getCity();
}
In DI Unity will resolve this interface implementation for you. In order to test this you'll have to create a fake class that implements your interface, and inject (on the constructor).
Something like:
public class FakeClass : IGettProxy {
public Task<List<CityDetails>> getCity(){
// here goes your fake implementation, to be injected on your controller.
}
// Remember to implement the other method
}
Then when you instantiate your controller you're going to pass this fake implementation of the interface (that what the constructor requires).
And now you can test it.