I have a pretty straight forward ApiController which works fine on Win7 but on Windows 2003 Server I get an error.
The get request (from either the browser or $.getJson):
https://site.com:61656/AD/Authenticate?UserName=xxxx&Password=xxxxx&AuthKey=xxxxxx
I get the following error:
<Exception xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/System.Web.Http.Dispatcher">
<ExceptionType>System.InvalidOperationException</ExceptionType>
<Message>
No MediaTypeFormatter is available to read an object of type 'InputModel' from content with media type ''undefined''.
</Message>
<StackTrace>
at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)
</StackTrace>
</Exception>
I am using the 5/1/2012 nuget nightly build packages. It looks like the objectContent.Value is coming through null on Windows 2003 Server but not on Windows 7 in the following line in HttpContentExtensions.cs:
if (objectContent != null && objectContent.Value != null && type.IsAssignableFrom(objectContent.Value.GetType()))
{
return TaskHelpers.FromResult((T)objectContent.Value);
}
The controller action:
[AcceptVerbs("GET", "POST")]
public ResultModel Authenticate(InputModel inputModel)
{
var test = ControllerContext.Request.Content.Headers.ContentType;
//Console.WriteLine(test.MediaType);
try
{
Console.WriteLine("AD Authorize request received: " + inputModel.UserName);
var ldap = new LdapAuthentication();
return ldap.Authenticate(inputModel);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return new ResultModel();
}
}
The MediaType comes through null on Win7 but on Windows 2003 server the request never makes it to the controller action.
Is there a way to specify a default media formatter which would handle the "'undefined'" media type?
EDIT:
Here is the input model:
public class InputModel {
public string UserName { get; set; }
public string Password { get; set; }
public string AuthKey { get; set; }
}
And here is the (self host) config:
var config = new HttpsSelfHostConfiguration(ConfigurationManager.AppSettings["serviceUrl"]);
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
config.Routes.MapHttpRoute("default", "{controller}/{action}");
var server = new HttpSelfHostServer(config);
try
{
server.OpenAsync().Wait();
Console.WriteLine("Waiting...");
EDIT #2:
I have noticed more interesting Win7 vs Windows 2003 Server behavior. If I remove the InputModel parameter on the controller action, the action is invoked while running on both Win7 and Windows 2003 Server. However on Win7 it returns JSON from both GET an POST requests. On Windows 2003 Server it returns XML from GET and JSON from POST.
This led me to testing the InputModel parameter using a POST. I have verified that the action is invoked correctly and the InputModel parameter is bound on Windows 2003 Server but only when using POST. So the workaround would be to grab the parameters manually on a GET. This allows jQuery's $.getJSON to work against a self hosted server under Windows 2003 Server:
[AcceptVerbs("GET")]
public ResultModel Authenticate()
{
try
{
var inputModel = new InputModel();
var query = ControllerContext.Request.RequestUri.ParseQueryString();
inputModel.UserName = query.GetValues("UserName") != null ? query.GetValues("UserName")[0] : null;
inputModel.Password = query.GetValues("Password") != null ? query.GetValues("Password")[0] : null;
inputModel.AuthKey = query.GetValues("AuthKey") != null ? query.GetValues("AuthKey")[0] : null;
Console.WriteLine("AD Authorize request received: " + inputModel.UserName);
var ldap = new LdapAuthentication();
return ldap.Authenticate(inputModel);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return new ResultModel();
}
}