简体   繁体   中英

Web API 'Request' is null

I'm trying to return an HttpResponseException from a POST Web API action using 'Request':

throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, "File not in a correct size"));

When doing so, I get Value cannot be null. Parameter name: request Value cannot be null. Parameter name: request .

Essentially - Request is null.

What am I missing?

Thank you

I found that my Request object was null within my ApiController because I have nested one ApiController call within another. The second, nested ApiController was therefore never initialized. You can't initialize it manually, but you can leverage the setter on the Request object to pass from wrapper to nested ApiController. A mockup is below, in my real code it fixed my Request.CreateErrorResponse(...) error.

public class WrapperController : ApiController
{
    // POST api/wrapper
    public void Post(ComplexWithChild value)
    {
        var other = value.otherdata;

        var childcontroller = new ChildController();
        childcontroller.Post(value.child); // ChildController is not initialized, and has null Request
        /*inside ChildController...// causes null reference exception due to null Request
            Request.CreateErrorResponse(HttpStatusCode.BadRequest, "my message"); 
        */

        childcontroller.Request = this.Request;
        childcontroller.Post(value.child); // ChildController uses same Request
        /*inside ChildController...// this works now
            Request.CreateErrorResponse(HttpStatusCode.BadRequest, "my message"); 
        */
    }
}

public class ChildController : ApiController
{
    public void Post(Child value)
    {
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "my message"));
    }
}

Use this:

HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.InternalServerError);
message.Content = new ObjectContent(typeof(MessageResponse), "Invalid Size", GlobalConfiguration.Configuration.Formatters.JsonFormatter);
throw new HttpResponseException(message);

Note: you can change "Invalid Size" with any object you may want to return for the user. eg:

public ErrorMessage
{
     public string Error;
     public int ErrorCode;
}

ErrorMessage msg = new ErrorMessage();
msg.Error = "Invalid Size";
msg.ErrorCode = 500;

HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.InternalServerError);
message.Content = new ObjectContent(typeof(MessageResponse), msg, GlobalConfiguration.Configuration.Formatters.JsonFormatter);
throw new HttpResponseException(message);

Another solution for people like @DavB.cs who have nested ApiControllers like:

public class ParentController : ApiController
{
    public IHttpActionResult Foo()
    {
       ChildRepository.Foo();
       return Ok(...);
    }
}

public class ChildRepository : ApiController
{
    public HttpResponseMessage Foo()
    {
        // Do something
        return Request.CreateResponse(...);
    }
}

Is simply to just pass in Request from the ParentController as such:

public class ParentController : ApiController
    {
        public IHttpActionResult Foo()
        {
           ChildRepository.Foo(Request);
           return Ok(...);
        }
    }

    public class ChildRepository
    {
        public HttpResponseMessage Foo(HttpRequestMessage request)
        {
            // Do something
            return request.CreateResponse(...);
        }
    }

Request comes from ApiController. This will get you past the 'Request is null' issue.

Hope this helps someone.

nizari's answer is correct however I ended up using the following:

throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content = new StringContent("Invalid image dimensions. Image file must be " + image.Width + "x" + image.Height + "px"),
                        StatusCode = HttpStatusCode.Forbidden
                    });

and accessing the content on client side using jqXHR.responseText

Thanks everyone!

Expanding on nizari's answer, Here's what I did in order to include a list of ErrorMessage objects:

IEnumerable errorList = new List<ErrorMessage>();

// ...

var error = new HttpError( "There were errors." ) 
{
    { "Errors", errorList }
};

var message = new HttpResponseMessage( HttpStatusCode.BadRequest )
{
    Content = new ObjectContent<HttpError>( error, GlobalConfiguration.Configuration.Formatters.JsonFormatter )
};

throw new HttpResponseException( message );

you have to create a new instance of the System.Net.Http.HttpRequestMessage. the below would work

var request = new HttpRequestMessage();
var response = request.CreateErrorResponse(HttpStatusCode.NotFound, "File not in a correct size");

throw new HttpResponseException(response);
HttpResponseMessage message = new  HttpResponseMessage(HttpStatusCode.InternalServerError); 
message.Content = new ObjectContent(typeof(MessageResponse),
                                    "Invalid Size",
                                    GlobalConfiguration.Configuration.Formatters.JsonFormatter); 
throw new HttpResponseException(message);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM