Manipulando solicitações de CORS Preflight para ações da ASP.NET MVC
Estou tentando executar uma solicitação POST entre domínios para uma ação do controlador ASP.NET MVC. Esta ação do controlador aceita e usa vários parâmetros. O problema é que quando a solicitação de preflight acontece, a ação do controlador realmente tenta executar e porque a solicitação OPTIONS não passa nenhum dado, a ação do controlador lança um erro HTTP 500. Se eu remover o código que usa o parâmetro ou o próprio parâmetro, toda a cadeia de solicitações será concluída com êxito.
Um exemplo de como isso é implementado:
Ação do Controlador
public ActionResult GetData(string data)
{
return new JsonResult
{
Data = data.ToUpper(),
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
Código do lado do cliente
<script type="text/javascript">
$(function () {
$("#button-request").click(function () {
var ajaxConfig = {
dataType: "json",
url: "http://localhost:8100/host/getdata",
contentType: 'application/json',
data: JSON.stringify({ data: "A string of data" }),
type: "POST",
success: function (result) {
alert(result);
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Error: Status: ' + textStatus + ', Message: ' + errorThrown);
}
};
$.ajax(ajaxConfig);
});
});
</script>
Agora, sempre que a solicitação de comprovação acontece, ela retorna um código HTTP 500, porque o parâmetro "data" é nulo, visto que a solicitação OPTIONS não passa nenhum valor.
O aplicativo do servidor foi configurado no IIS local na porta 8100 e a página que executa o código do lado do cliente está configurada na porta 8200 para imitar as chamadas de domínio cruzado.
Eu também configurei o host (em 8100) com os seguintes cabeçalhos:
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Origin: http://localhost:8200
Uma solução que eu encontrei, foi verificar o método HTTP que executa a ação e se é uma solicitação OPTIONS para retornar apenas o conteúdo em branco, caso contrário, execute o código de ação. Igual a:
public ActionResult GetData(string data)
{
if (Request.HttpMethod == "OPTIONS") {
return new ContentResult();
} else {
return new JsonResult
{
Data = data.ToUpper(),
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
Mas essa abordagem parece muito desajeitada para mim. Eu considerei adicionar este tipo de lógica a umAttribute
, mas mesmo isso significaria decorar cada ação que será chamada usando o CORS com ela.
Existe uma solução mais elegante para que essa funcionalidade funcione?