Reputation: 21
I'm using BreezeJs on both server and client side. I have the following controller action. I wish to get an 404 http code when a product code is not found.
public Product GetProduct(string code)
{
var p = _contextProvider.Context.Products.Where(p => p.Code == code).FirstOrDefault();
if (p == null)
{
//does not work because because breeze swallows the exception
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return p;
}
Below is the response. The HttpResponseException is swallowed by the BreezeApi. Any ideas? Thank you in advance.
{
"$id": "1",
"$type": "System.Web.Http.HttpError, System.Web.Http",
"Message": "An error has occurred.",
"ExceptionMessage": "Cannot perform runtime binding on a null reference",
"ExceptionType": "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException",
"StackTrace": " at CallSite.Target(Closure , CallSite , Object )\r\n at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)\r\n at Breeze.WebApi.ODataActionFilter.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)\r\n at System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecuted(HttpActionContext actionContext, HttpResponseMessage response, Exception exception)\r\n at System.Web.Http.Filters.ActionFilterAttribute.<>c__DisplayClass2.<System.Web.Http.Filters.IActionFilter.ExecuteActionFilterAsync>b__0(HttpResponseMessage response)\r\n at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass41`2.<Then>b__40(Task`1 t)\r\n at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)"
}
Upvotes: 2
Views: 1098
Reputation: 17052
This should be fixed now in breeze 0.73.1. i.e. throwing a HttpResponseException will now return that exception to the client.
Upvotes: 2
Reputation: 12184
The action filter Breeze is using is not designed to handle NULL
Content values.
You can work around it if you generate the not found response this way, Note there is some content in this Not Found repsonse i.e. the string message.
public HttpResponseMessage GetProduct(string code)
{
var p = _contextProvider.Context.Products.Where(p => p.Code == code).FirstOrDefault();
if (p == null)
{
Request.CreateErrorResponse(HttpStatusCode.NotFound, "Couldn't find the resource");
}
Request.CreateResponse(HttpStatusCode.OK, p);
}
I think this is a bug in Breeze.
The code for Breeze should probably be altered to not attempt to parse faulted responses (!actionExecutedContext.Response.IsSuccessStatusCode
) or make proper use of its TryGetContentValue
and escape the method if it fails to retrieve the content (as it stands it ignores the false returned if it fails to retrieve the content).
public class ODataActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
}
/// <summary>
/// Called when the action is executed.
/// </summary>
/// <param name="actionExecutedContext">The action executed context.</param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response == null)
{
return;
}
if(!actionExecutedContext.Response.IsSuccessStatusCode)
{
return;
}
And/Or at least a simple Null reference check here:
public class ODataActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
}
/// <summary>
/// Called when the action is executed.
/// </summary>
/// <param name="actionExecutedContext">The action executed context.</param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (actionExecutedContext.Response == null)
{
return;
}
object responseObject;
if(!actionExecutedContext.Response.TryGetContentValue(out responseObject))
{
return;
}
Upvotes: 2