Our OData endpoint is self-hosted(OWIN). For single request: creating, updating, patching and deleting everything works great, but the problem is when I send batch request with multiple actions in it, I'm having problem with basic authorization. I read a lot of articles, but still cannot solve the issue. In OData documentation it says:
Each MIME part body that represents a single request MUST NOT include:
• authentication or authorization related HTTP headers
So, If I set Authorization to batch request, but don't set to each single request in batch, I'm getting null in actionContext.Request.Headers.Authorization in OnAuthorization method. My question is: how can I get Batch request's Authorization header from request in this Batch?
In endpoint Batch is enabled:
HttpConfiguration config = new HttpConfiguration();
var odataBatchHandler = new DefaultODataBatchHandler(new HttpServer(config));
config.MapODataServiceRoute("ODataApi", null, builder.GetEdmModel(), odataBatchHandler);
config.Count().Filter().OrderBy().Expand().MaxTop(null).Select();
appBuilder.UseWebApi(config);
Here is the authorization logic:
public class ODataBasicAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
//Question: here Authorization property is null, because this is Get request for SAStudent
if (actionContext.Request.Headers.Authorization == null || actionContext.Request.Headers.Authorization.Scheme != "Basic")
{
HandleUnauthorizedRequest(actionContext);
}
else
{
ISession session = Login(actionContext.Request);
if (session == null)
{
HandleUnauthorizedRequest(actionContext);
}
else
{
IsAuthorized(actionContext);
}
}
}
}
Here is the test:
[TestMethod]
public void BatchRequestTest()
{
var odataAddress = "https://localhost:23170/Sample/Sample/OData/";
var batchUrl = $"{odataAddress}$batch";
HttpClient http = new HttpClient();
// Global batch request
HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, batchUrl);
batchRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", "QWRtaW5pc3RyYXRvcjpwdw==");
MultipartContent batchContent = new MultipartContent("mixed", "batch_" + Guid.NewGuid().ToString());
var getStudent = new HttpRequestMessage(HttpMethod.Get, $"{odataAddress}SAStudent");
//getStudent.Headers.Authorization = new AuthenticationHeaderValue("Basic", "QWRtaW5pc3RyYXRvcjpwdw==");
// First message content with GET request
HttpMessageContent getRequestContent_1 = new HttpMessageContent(getStudent);
getRequestContent_1.Headers.Remove("Content-Type");
getRequestContent_1.Headers.Add("Content-Type", "application/http");
getRequestContent_1.Headers.Add("Content-Transfer-Encoding", "binary");
// Add this GET content to the batch content
batchContent.Add(getRequestContent_1);
var getPassport = new HttpRequestMessage(HttpMethod.Get, $"{odataAddress}SAPassport");
//getPassport.Headers.Authorization = new AuthenticationHeaderValue("Basic", "QWRtaW5pc3RyYXRvcjpwdw==");
// Second message content with GET request
HttpMessageContent getRequestContent_2 = new HttpMessageContent(getPassport);
getRequestContent_2.Headers.Remove("Content-Type");
getRequestContent_2.Headers.Add("Content-Type", "application/http");
getRequestContent_2.Headers.Add("Content-Transfer-Encoding", "binary");
// Add this GET content to the batch content
batchContent.Add(getRequestContent_2);
// Here we go
batchRequest.Content = batchContent;
HttpResponseMessage response = http.SendAsync(batchRequest).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
}
If I set Authorization to each single request in Batch request than it will work, but It seems not correct, so setting only authorization header to Batch should work.
Any ideas?
Thanks in advance,