I have the following private method allows me to Mock and therfore test a HttpClient
private Mock<HttpClient> GetMockHttClient(HttpStatusCode desiredStatusCode, User user)
{
var httpMessageHandler = new Mock<HttpMessageHandler>();
httpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync((HttpRequestMessage request, CancellationToken token) =>
{
var response = new HttpResponseMessage
{
Content = new StringContent(JsonSerializer.Serialize(user)), //<-- this could be anything
ReasonPhrase = null,
RequestMessage = null,
StatusCode = desiredStatusCode,
Version = new Version(1, 0)
};
return response;
});
var httpClientMock = new Mock<HttpClient>(httpMessageHandler.Object)
{
Object =
{
BaseAddress = new Uri("[Redacted]")
}
};
return httpClientMock;
}
For now I am passing in a User object, however I have other tests where I might for example want an int[] serializing, or a List<User> serializing.
It seems ridiculous to copy and paste this method and change the object I wish to serialize, so how can I make this method generic so that when I call it, I can specify the type that will be serialized to json.
private Mock<HttpClient> GetMockHttClient<TModel>(HttpStatusCode desiredStatusCode, TModel model)
{
var httpMessageHandler = new Mock<HttpMessageHandler>();
httpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync((HttpRequestMessage request, CancellationToken token) =>
{
var response = new HttpResponseMessage
{
Content = new StringContent(JsonSerializer.Serialize<TModel>(model)),
ReasonPhrase = null,
RequestMessage = null,
StatusCode = desiredStatusCode,
Version = new Version(1, 0)
};
return response;
});
var httpClientMock = new Mock<HttpClient>(httpMessageHandler.Object)
{
Object =
{
BaseAddress = new Uri("[Redacted]")
}
};
return httpClientMock;
}
Related
I am writing some tests where the class I'm testing depends on HttpClient. To mock that I am mocking a HttpMessageHandler and pass that to the HttpClient constructor.
To accomplish this I have a base class:
public class HttpTestBase
{
protected static readonly string BaseAddress = "https://test.com";
protected readonly HttpClient _httpClient;
protected readonly Mock<HttpMessageHandler> _httpMessageHandlerMock;
public HttpTestBase()
{
_httpMessageHandlerMock = new Mock<HttpMessageHandler>();
_httpClient = new HttpClient(_httpMessageHandlerMock.Object);
_httpClient.BaseAddress = new Uri(BaseAddress);
}
protected void MockHttpResponse(HttpResponseMessage message, string expectedPath, HttpMethod expectedMethod)
{
_httpMessageHandlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.Is<HttpRequestMessage>(request => AssertRequestParameters(expectedPath, expectedMethod, request)),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(message);
}
private bool AssertRequestParameters(string expectedPath, HttpMethod expectedMethod, HttpRequestMessage request)
{
// Throw an exception if the method or path does not match what is expected.
}
}
And then a test looks as follows, in a test class inheriting this test base:
[Fact]
public async Task GetAvailableLicenseCount()
{
// Arrange
var licenses = new JsonObject
{
["total_seats_consumed"] = 4500,
["total_seats_purchased"] = 5000
};
MockHttpResponse(
new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(licenses.ToJsonString()) },
expectedPath: "/enterprises/enterprise/consumed-licenses",
expectedMethod: HttpMethod.Get
);
// Act
var result = await sut.GetAvailableLicenseCount();
// Assert
result.Should().Be(500);
}
This works well when a method only performs a single call. Some methods perform multiple calls in a sequence. I have solved that partially, but I would still like to have the assertion in the setup (e.g. when I call AssertRequestParameters).
To support multiple calls in a chain, I instead did this in the base class:
protected void AddHttpMockResponse(HttpResponseMessage message, string expectedPath, HttpMethod expectedMethod)
{
_responseMocks.Enqueue(new HttpMock
{
Response = message,
Assertion = new Assertion { ExpectedPath = expectedPath, ExpectedMethod = expectedMethod }
});
}
protected void MockHttpResponses()
{
_httpMessageHandlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(() => _responseMocks.Dequeue().Response);
}
As you can see I have removed the assertion in the setup, because it seems that the assertions collide and I get the wrong return value from the mock.
To use this, I refactored the test as follows:
[Fact]
public async Task GetAvailableLicenseCount()
{
// Arrange
var licenses = new JsonObject
{
["total_seats_consumed"] = 4500,
["total_seats_purchased"] = 5000
};
AddHttpMockResponse(
new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(licenses.ToJsonString()) },
expectedPath: "/enterprises/enterprise/consumed-licenses",
expectedMethod: HttpMethod.Get
);
MockHttpResponses();
// Act
var result = await sut.GetAvailableLicenseCount();
// Assert
result.Should().Be(500);
}
This also works well for multiple responses from the same mock.
However, I would like to be able to mock multiple responses where the response is determined by what I use in the Setup of the mock. The reason I want to do this is that I cannot use Verify on HttpMessageHandler as the method is not accessible to me.
Is it possible to achieve a dynamic return value based on what is done in the setup of the mock?
If I understand your question correctly you'll want something like this:
I recently had to do a similar thing and found the below article very helpful. Check the 'Mock HttpMessageHandler Using Moq' section. It shows you how to return a HttpResponseMessage object you create, which is what I think you might want.
https://code-maze.com/csharp-mock-httpclient-with-unit-tests/
Field on your class
private readonly Mock<HttpMessageHandler> _httpMessageHandlerStub;
In your setup (constructor or a separate method)
_httpMessageHandlerStub = new Mock<HttpMessageHandler>();
var httpClient = new HttpClient(_httpMessageHandlerStub.Object);
_sut = new SomeService(
httpClient,
anotherDependency
)
And then you can configure the below in each test
[Fact]
public async Task GetListAsync_Successfully_Uses_Api_Key()
{
var unauthorisedResponseMessage = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized)
{
Content = new StringContent($"'{_apiKeyHeaderName}' header not found or API key is incorrect")
};
var successResponseMessage = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
Content = new StringContent(JsonConvert.SerializeObject(new List<SomeDto>()))
};
// Return 200 if api key header is present and the value is correct.
_httpMessageHandlerStub.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.Is<HttpRequestMessage>(x => x.Method == HttpMethod.Get && x.Headers.Any(h => h.Key == _apiKeyHeaderName && h.Value.FirstOrDefault() == _apiKeyHeaderValue)),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(successResponseMessage);
// Return 401 is api key header is not present or api key value is incorrect.
_httpMessageHandlerStub.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.Is<HttpRequestMessage>(x => x.Method == HttpMethod.Get && !x.Headers.Any(h => h.Key == _apiKeyHeaderName && h.Value.FirstOrDefault() == _apiKeyHeaderValue)),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(unauthorisedResponseMessage);
var result = _sut.GetListAsync();
// Assert stuff...
}
Hope that's helpful.
I have a web api end point that i want to unit test. I have a custom SwaggerUploadFile attribute that allows a file upload button on the swagger page. But for unit testing I cant figure out how to pass in a file.
For unit testing I am using: Xunit, Moq and Fluent Assertions
Below is my controller with the endpoint:
public class MyAppController : ApiController
{
private readonly IMyApp _myApp;
public MyAppController(IMyApp myApp)
{
if (myApp == null) throw new ArgumentNullException(nameof(myApp));
_myApp = myApp;
}
[HttpPost]
[ResponseType(typeof(string))]
[Route("api/myApp/UploadFile")]
[SwaggerUploadFile("myFile", "Upload a .zip format file", Required = true, Type = "file")]
public async Task<IHttpActionResult> UploadFile()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = await Request.Content.ReadAsMultipartAsync();
var bytes = await provider.Contents.First().ReadAsByteArrayAsync();
try
{
var retVal = _myApp.CheckAndSaveByteStreamAsync(bytes).Result;
if(retVal)
{
return
ResponseMessage(
new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "File has been saved"
}), Encoding.UTF8, "application/json")
});
}
return ResponseMessage(
new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "The file could not be saved"
}), Encoding.UTF8, "application/json")
});
}
catch (Exception e)
{
//log error
return BadRequest("Oops...something went wrong");
}
}
}
Unit test I have so far:
[Fact]
[Trait("Category", "MyAppController")]
public void UploadFileTestWorks()
{
//Arrange
_myApp.Setup(x => x.CheckAndSaveByteStreamAsync(It.IsAny<byte[]>())).ReturnsAsync(() => true);
var expected = JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "The file has been saved"
});
var _sut = new MyAppController(_myApp.Object);
//Act
var retVal = _sut.UploadFile();
var content = (ResponseMessageResult)retVal.Result;
var contentResult = content.Response.Content.ReadAsStringAsync().Result;
//Assert
contentResult.Should().Be(expected);
}
The above fails as when it hits this line if(!Request.Content.IsMimeMultipartContent()) we get a NullReferenceException > "{"Object reference not set to an instance of an object."}"
Best Answer Implemented:
Created an interface:
public interface IApiRequestProvider
{
Task<MultipartMemoryStreamProvider> ReadAsMultiPartAsync();
bool IsMimeMultiPartContent();
}
Then an implementation:
public class ApiRequestProvider : ApiController, IApiRequestProvider
{
public Task<MultipartMemoryStreamProvider> ReadAsMultiPartAsync()
{
return Request.Content.ReadAsMultipartAsync();
}
public bool IsMimeMultiPartContent()
{
return Request.Content.IsMimeMultipartContent();
}
}
Now my controller uses constructor injection to get the RequestProvider:
private readonly IMyApp _myApp;
private readonly IApiRequestProvider _apiRequestProvider;
public MyAppController(IMyApp myApp, IApiRequestProvider apiRequestProvider)
{
if (myApp == null) throw new ArgumentNullException(nameof(myApp));
_myApp = myApp;
if (apiRequestProvider== null) throw new ArgumentNullException(nameof(apiRequestProvider));
_apiRequestProvider= apiRequestProvider;
}
New implementation on method:
[HttpPost]
[ResponseType(typeof(string))]
[Route("api/myApp/UploadFile")]
[SwaggerUploadFile("myFile", "Upload a .zip format file", Required = true, Type = "file")]
public async Task<IHttpActionResult> UploadFile()
{
if (!_apiRequestProvider.IsMimeMultiPartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = await _apiRequestProvider.ReadAsMultiPartAsync();
var bytes = await provider.Contents.First().ReadAsByteArrayAsync();
try
{
var retVal = _myApp.CheckAndSaveByteStreamAsync(bytes).Result;
if(retVal)
{
return
ResponseMessage(
new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "File has been saved"
}), Encoding.UTF8, "application/json")
});
}
return ResponseMessage(
new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "The file could not be saved"
}), Encoding.UTF8, "application/json")
});
}
catch (Exception e)
{
//log error
return BadRequest("Oops...something went wrong");
}
}
}
And my unit test that mocks the ApiController Request:
[Fact]
[Trait("Category", "MyAppController")]
public void UploadFileTestWorks()
{
//Arrange
_apiRequestProvider = new Mock<IApiRequestProvider>();
_myApp = new Mock<IMyApp>();
MultipartMemoryStreamProvider fakeStream = new MultipartMemoryStreamProvider();
fakeStream.Contents.Add(CreateFakeMultiPartFormData());
_apiRequestProvider.Setup(x => x.IsMimeMultiPartContent()).Returns(true);
_apiRequestProvider.Setup(x => x.ReadAsMultiPartAsync()).ReturnsAsync(()=>fakeStream);
_myApp.Setup(x => x.CheckAndSaveByteStreamAsync(It.IsAny<byte[]>())).ReturnsAsync(() => true);
var expected = JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "The file has been saved"
});
var _sut = new MyAppController(_myApp.Object, _apiRequestProvider.Object);
//Act
var retVal = _sut.UploadFile();
var content = (ResponseMessageResult)retVal.Result;
var contentResult = content.Response.Content.ReadAsStringAsync().Result;
//Assert
contentResult.Should().Be(expected);
}
Thanks to #Badulake for the idea
You should do a better separation in the logic of the method.
Refactor your method so it does not depends on any class related to your web framework , in this case the Request class. Your upload code does not need to know anything about it.
As a hint:
var provider = await Request.Content.ReadAsMultipartAsync();
could be transformed to:
var provider = IProviderExtracter.Extract();
public interface IProviderExtracter
{
Task<provider> Extract();
}
public class RequestProviderExtracter:IProviderExtracter
{
public Task<provider> Extract()
{
return Request.Content.ReadAsMultipartAsync();
}
}
In your tests you can easely mock IProviderExtracter and focus in which work is doing each part of your code.
The idea is you get the most decoupled code so your worries are focused only in mocking the classes you have developed, no the ones the framework forces you to use.
The below was how I initially solved it but after Badulake's answer i implemented that where i abstracted the api request to an interface/class and Mocked it out with Moq. I edited my question and put the best implementation there, but i left this answer here for people who dont want to go to the trouble of mocking it
I used part of this guide but I made a simpler solution:
New unit test:
[Fact]
[Trait("Category", "MyAppController")]
public void UploadFileTestWorks()
{
//Arrange
var multiPartContent = CreateFakeMultiPartFormData();
_myApp.Setup(x => x.CheckAndSaveByteStreamAsync(It.IsAny<byte[]>())).ReturnsAsync(() => true);
var expected = JsonConvert.SerializeObject(
new WebApiResponse
{
Message = "The file has been saved"
});
_sut = new MyAppController(_myApp.Object);
//Sets a controller request message content to
_sut.Request = new HttpRequestMessage()
{
Method = HttpMethod.Post,
Content = multiPartContent
};
//Act
var retVal = _sut.UploadFile();
var content = (ResponseMessageResult)retVal.Result;
var contentResult = content.Response.Content.ReadAsStringAsync().Result;
//Assert
contentResult.Should().Be(expected);
}
Private support method:
private static MultipartFormDataContent CreateFakeMultiPartFormData()
{
byte[] data = { 1, 2, 3, 4, 5 };
ByteArrayContent byteContent = new ByteArrayContent(data);
StringContent stringContent = new StringContent(
"blah blah",
System.Text.Encoding.UTF8);
MultipartFormDataContent multipartContent = new MultipartFormDataContent { byteContent, stringContent };
return multipartContent;
}
I'm trying to write a unit test for polly, but it looks like the return is cached.
Method PostAsyncWithRetry:
using Polly;
using System;
using System.Diagnostics;
using System.Net.Cache;
using System.Net.Http;
public class RetryClient
{
private HttpClient httpClient = new HttpClient(new WebRequestHandler()
{ CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore) });
public HttpResponseMessage PostAsyncWithRetry(
String url,
String path,
StringContent httpContent)
{
httpClient.BaseAddress = new Uri(url);
var retryPolicy =
Policy.Handle<HttpRequestException>()
.OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
.RetryAsync(3, (exception, retryCount, context) =>
{
Debug.WriteLine("RetryCount: {0}", retryCount);
});
var response = retryPolicy.ExecuteAsync(async () =>
{
return await httpClient.PostAsync(path, httpContent);
}
);
return response.Result;
}
}
Test:
[TestFixture]
class Test
{
private HttpClient mockHTTPClient;
private Mock<WebRequestHandler> mockHttpMessageHandler;
private RetryClient testInstance;
private const String URL = "https://aaa.com";
private const String PATH = "/path";
private const String EXPECTED_STRING_CONTENT = "Some return text";
[SetUp]
public void SetUp()
{
testInstance = new RetryClient();
mockHttpMessageHandler = new Mock<WebRequestHandler>();
mockHttpMessageHandler.Object.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
mockHTTPClient = new HttpClient(mockHttpMessageHandler.Object);
var type = typeof(RetryClient);
var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
fields[0].SetValue(testInstance, mockHTTPClient);
}
[Test]
public void TestMEEEE()
{
var responses = new Queue<Task<HttpResponseMessage>>();
responses.Enqueue(Task.FromResult(new HttpResponseMessage
{
StatusCode = HttpStatusCode.NotFound,
Content = new StringContent(EXPECTED_STRING_CONTENT)
}));
responses.Enqueue(Task.FromResult(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(EXPECTED_STRING_CONTENT)
}));
var postContent = new StringContent(EXPECTED_STRING_CONTENT);
mockHttpMessageHandler.Protected()
.Setup<Task>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.Returns(responses.Dequeue());
var response = testInstance.PostAsyncWithRetry(
URL, PATH, postContent);
mockHttpMessageHandler.Verify();
Assert.AreEqual(responses.Count, 0, "didn't dequeue");
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Incorrect status code");
}
}
Not sure why, but it looks like the responses queue is only being Dequeue once, this leads me to believe the response is being cache. Does anyone know who is caching the response, and how do I disable it?
Thanks a bunch in advance!
I figured it out. It has nothing to do with caching. During the mock setup, it stores the Dequeue value as a return instead of invoking it every time.
Changing it to () => responses.Dequeue() works now.
Thank you guys!
In the below code,I need to check whether in the request "System" is added with the value "Portal".
var rq = new RestBaseRequest{AmendHeaders = x => x.Add("Systerm", "Portal")};
var repositoryResponse = await this.restRepository.GetAsync(rq,cancellationToken, loggingContext);
The RestBaseRequest class looks like below
public class RestBaseRequest
{
public RestBaseRequest();
public Action<HttpRequestHeaders> AmendHeaders { get; set; }
}
I tried the way as below
[Test]
public async Task TestRequestHeaderConatainsRequestingSystem()
{
// Arrange
var restRepository = new Mock<IRestRepository<LifeBondResponse>>();
RestBaseRequest requestBase = null;
CancellationToken token = new CancellationToken();
LoggingContext context = null;
restRepository.Setup(x => x.GetAsync(
It.IsAny<RestBaseRequest>(),
It.IsAny<CancellationToken>(),
It.IsAny<LoggingContext>())).Callback((RestBaseRequest baseRequest, CancellationToken cancellationToken, LoggingContext loggingContext) =>
{
requestBase = baseRequest;
token = cancellationToken;
context = loggingContext;
})
.ReturnsAsync(new Service<LifeBondResponse>
{
Status = GeneralResponseType.Success,
});
var request = new CustomerRequest<InvestmentBondPolicy>
{
TypeOfRequest = CustomerRetrieveType.Number,
Id = "12345",
Data = new Policy()
{
PolicyNumber = "123456",
}
};
var repository = new BondRepository(this.authoriseService.Object, restRepository.Object);
var rs = await repository.GetPolicyAsync(request, new CancellationToken());
}
since there is no public properties in RestBaseRequest,I couldn't able to do check further.Is there any way to test this or suggestions?
I got it myself,
[Test]
public async Task TestRequestHeaderConatainsRequestingSystem()
{
// Arrange
var restRepository = new Mock<IRestRepository<LifeBondResponse>>();
var client = new HttpClient();
restRepository
.Setup(
x => x.GetAsync(
It.IsAny<RestBaseRequest>(),
It.IsAny<CancellationToken>(),
It.IsAny<ILoggingContext>()))
.Callback((RestBaseRequest serviceRequest,
CancellationToken cancellationToken,
ILoggingContext loggingContext) =>
{
serviceRequest.AmendHeaders(client.DefaultRequestHeaders);
}).ReturnsAsync(new Service<LifeBondResponse> { Status = GeneralResponseType.Success, });
var request = new CustomerRequest<Policy>
{
TypeOfRequest = CustomerRetrieveType.PolicyNumber,
Id = "12345",
Data = new Policy()
{
PolicyNumber = "123456",
}
};
var repository = new LifeBondRepository(this.authoriseService.Object, restRepository.Object);
// Act
await repository.GetPolicyAsync(request, new CancellationToken());
// Assert
client.DefaultRequestHeaders.Should().NotBeNull();
client.DefaultRequestHeaders.Any(x => x.Key == "System").Should().Be(true);
client.DefaultRequestHeaders.GetValues("System").First().Should().Be("Portal");
}
I suggest two tests:
one that checks that GetAsync calls the callback on the request
another one that checks that this concrete request adds Portal to System
In the first one you pass a mocked request into the repository and in the second, call the callback with a mocked HttpRequestHeaders.
The second test might look like this:
var headers = new HttpRequestHeaders();
requestToTest.AmendHeaders( headers );
Assert.That( headers["System"], Is.EqualTo( "Portal" ) );
Full text:
public void MethodToTest( IRepository repository )
{
var rq = new RestBaseRequest{AmendHeaders = x => x.Add("Systerm", "Portal")};
var repositoryResponse = await repository.GetAsync(rq,cancellationToken, loggingContext);
}
public void TheTest()
{
repositoryMock.Setup( x => x.GetAsync(...) ).Callback( (x,y,z) =>
{
var headers = new HttpRequestHeaders();
x.AmendHeaders( headers );
Assert.That( headers["System"], Is.EqualTo( "Portal" ) );
});
_subjectUnderTest.MethodToTest( repositoryMock.Object );
}
I am working with ASP.NET Web Api 2. I have created a action filter which checks for incoming request and then return a response back based on certain condition.
public override void OnAuthorization(HttpActionContext actionContext)
{
var req = actionContext.Request;
if (!req.Headers.Contains("x-key") || req.Headers.GetValues("x-key") == null)
{
actionContext.Response = req.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Content = new StringContent("Token required", Encoding.UTF8, "text/html");
}
}
I want to know is this the right way to return JSON response? I want to return a custom object (
var rebBody = new {message = "Unauthorized", payload = "", response = "401"};) as JSON in the response body.
Does it make sense to use something like this:
var v = new {message = "Unauthorized", payload = "", response = "401"};
actionContext.Response.Content = new ObjectContent<object>(v, new JsonMediaTypeFormatter(), "application/json");
Something like this perhaps,
public override void OnAuthorization(HttpActionContext actionContext)
{
var req = actionContext.Request;
if (!req.Headers.Contains("x-key") || req.Headers.GetValues("x-key") == null)
{
HttpResponseMessage responseMessage = new HttpResponseMessage()
{
Content = new StringContent("{\"message\":\"Unauthorized\", \"payload\":\"\",\"response\":\"401\"}")
};
responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
actionContext.Response = responseMessage;
}
}
or like this:
public override void OnAuthorization(HttpActionContext actionContext)
{
var req = actionContext.Request;
if (!req.Headers.Contains("x-key") || req.Headers.GetValues("x-key") == null)
{
var v = new { message = "Unauthorized", payload = "", response = "401" };
HttpResponseMessage responseMessage = new HttpResponseMessage()
{
StatusCode = HttpStatusCodes.Unauthorized,
Content = new StringContent(JsonConvert.SerializeObject(v))
};
responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
actionContext.Response = responseMessage;
}
}
You can use another overload of CreateResponse:
public static HttpResponseMessage CreateResponse<T>(
this HttpRequestMessage request,
T value)
e.g:
var content = new { Property = 1 };
request.CreateResponse(content);
See: https://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessageextensions.createresponse(v=vs.118).aspx