Desde a atualização para RC para WebAPI, estou tendo um problema muito estranho ao chamar o POST na minha WebAPI. Eu até voltei à versão básica gerada no novo projeto. Assim:
public void Post(string value)
{
}
e ligando do Fiddler:
Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29
Body:
{
"value": "test"
}
Quando depuro, a string "value" nunca está sendo atribuída. É sempre sempre NULL. Alguém está tendo esse problema?
(Vi o problema pela primeira vez com um tipo mais complexo)
O problema não está vinculado apenas ao ASP.NET MVC 4, o mesmo problema ocorre para um projeto novo do ASP.NET MVC 3 após a instalação do RC
c#
.net
asp.net-web-api
asp.net-web-api-routing
ianrathbone
fonte
fonte
Respostas:
Como você possui apenas um parâmetro, tente decorá-lo com o
[FromBody]
atributo ou altere o método para aceitar um DTO com valor como uma propriedade, como sugeri aqui: Ligação de parâmetro do MVC4 RC WebApiATUALIZAÇÃO: o site oficial do ASP.NET foi atualizado hoje com uma excelente explicação: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 1
Em poucas palavras, ao enviar um único tipo simples no corpo, envie apenas o valor prefixado com um sinal de igual (=), por exemplo, body:
=test
fonte
=
à frente nunca funcionou para mim, até eu seguir o conselho de Jim em seu comentário (não como um objeto JSON) e funcionou. Isso é fundamental! Eu realmente não gosto de como WebAPI exigente é.:(
). Você realmente deve adicionar suporte ao formato que as pessoas esperam que ele aceite.Eu tenho coçado minha cabeça hoje.
Minha solução é mudar
[FromBody]
para umHttpRequestMessage
, essencialmente movendo a pilha HTTP.No meu caso, estou enviando dados através do fio que é zipado json que é então base64'd. Tudo isso em um aplicativo Android.
A assinatura original do meu endpoint da Web era assim (usando
[FromBody]
):Minha correção para esse problema foi voltar a usar a
HttpRequestMessage
para a assinatura do meu endpoint.Você pode obter acesso aos dados da postagem usando esta linha de código:
Isso funciona e permite o acesso aos dados brutos intocados da publicação. Você não precisa mexer com o violinista colocando um sinal = no início da sua string ou alterando o tipo de conteúdo.
Como um aparte, primeiro tentei seguir uma das respostas acima, que foi alterar o tipo de conteúdo para: "Tipo de conteúdo: application / x-www-form-urlencoded". Para dados brutos, esse é um mau conselho, porque retira + caracteres.
Portanto, uma sequência base64 que começa assim: "MQ0AAB + LCAAAAAA" termina assim "MQ0AAB LCAAAAAA"! Não é o que você quer.
Outro benefício do uso
HttpRequestMessage
é que você obtém acesso a todos os cabeçalhos http de dentro do seu endpoint.fonte
HttpRequestMessage request
assinatura do método, pois sempre a possui. No corpo do método, ele pode ser acessado noRequest
objeto. por exemploRequest.Content.ReadAsStringAsync().Result;
Acabei de ocorrer usando o Fiddler. O problema era que eu não havia especificado
Content-Type
.Tente incluir um cabeçalho
Content-Type
na sua solicitação POST.Como alternativa, conforme os comentários abaixo, pode ser necessário incluir um cabeçalho JSON
fonte
contentType: "application/x-www-form-urlencoded; charset=UTF-8"
, para obter um exemplo completo, veja Complete Cient and ServerEu também encontrei esse problema e foi assim que resolvi meu problema
código webapi:
Código do cliente:
fonte
some value
, entãodata
é nulo.Eu estava usando
Postman
e estava cometendo o mesmo erro .. passando ovalue
objeto as json em vez de stringClaramente, o acima está errado quando o parâmetro api é do tipo string.
Então, basta passar a string entre aspas duplas no corpo da API:
fonte
JSON.stringify
estava fazendo com que eu[frombody]
estivessenull
. Depois de definir o campo de dados para um valor de sequência (que é uma sequência json), funcionou.Tente criar uma classe para servir como modelo de dados e, em seguida, envie um objeto JSON com propriedades correspondentes às propriedades da sua classe de modelo de dados. (Nota: testei isso e funciona com o mais novo MVC 4 RC 2012 que baixei hoje).
O objeto JSON abaixo é enviado no corpo HTTP-POST, o tipo de conteúdo é application / json
Acredito que a razão pela qual você deve criar uma classe de modelo de dados é porque valores simples são assumidos como sendo dos parâmetros da URL e um único valor complexo é assumido como sendo do corpo. Eles têm os atributos
[FromBody]
e[FromUrl]
, mas o uso[FromBody] string value
ainda não funcionou para mim. Parece que eles ainda estão solucionando muitos bugs, então tenho certeza de que isso mudará no futuro.Edit: Tem XML para trabalhar no corpo. O serializador XML padrão foi alterado para DataContractSerializer em vez de XmlSerializer. Colocar a seguinte linha no meu arquivo Global.asax corrigiu esse problema ( referência )
fonte
Após algumas tentativas, acho que o comportamento padrão está correto e não há nada para invadir.
O único truque é: se o argumento do método post for
string
como abaixo, você deve enviar uma string simples com aspas duplas no corpo (ao usar ajax ou postman), por exemplo,Caso contrário, se você enviar uma string json no corpo da postagem sem aspas duplas externas e aspas internas escapadas, poderá ser analisada na classe de modelo (o tipo de argumento), por exemplo,
{"a":1, "b":2}
fonte
Eu estava procurando uma solução para esse problema por alguns minutos agora, então vou compartilhar minha solução.
Se você postar um modelo, seu modelo precisará ter um construtor vazio / padrão, caso contrário, o modelo não poderá ser criado, obviamente. Tenha cuidado ao refatorar. ;)
fonte
Isso funcionou para mim:
Crie uma classe C # DTO, com uma propriedade para cada atributo que você deseja passar do jQuery / Ajax
Defina o método da API da Web:
Chame a API da Web como tal:
fonte
Para aqueles que estão tendo o mesmo problema com o Swagger ou o Postman, como eu, se você estiver passando um atributo simples como string em um post, mesmo com o "ContentType" especificado, você ainda receberá um valor nulo.
Passando apenas:
MyValue
Irá entrar no controlador como nulo.
Mas se você passar:
"MyValue"
O valor vai acertar.
As citações fizeram a diferença aqui. Claro, isso é apenas para Swagger e Postman. Por exemplo, em um aplicativo Frontend usando Angular, isso deve ser resolvido pela estrutura automaticamente.
fonte
Eu tive o mesmo problema e descobri que, ao alterar o Tipo de conteúdo para "application / json", o problema não foi resolvido. No entanto, "application / json; charset = utf-8" funcionou.
fonte
Eu tive um problema semelhante em que o objeto de solicitação para o meu método de API da Web era sempre nulo. Notei que, como o nome da ação do controlador era prefixado com "Get", a API da Web tratava isso como um HTTP GET em vez de um POST. Depois de renomear a ação do controlador, agora funciona como pretendido.
fonte
Com o Angular, eu era capaz de passar dados neste formato:
E no Web API Controler:
Como alternativa, eu também poderia postar dados JSON como este:
E, no controlador, aceite um tipo de classe como este:
De qualquer maneira, se você tiver uma classe pública estabelecida na API, poste JSON, caso contrário, poste '=' + JSON.stringify ({..: ..., ..: ...})
fonte
No meu caso, o problema era que o parâmetro era uma string e não um objeto. Alterei o parâmetro para JObject do Newsoft.Json e funciona.
fonte
Adicionando linha
até o final da função
protected void Application_Start()
no Global.asax.cs corrigiu um problema semelhante para mim no ASP.NET MVC3.fonte
Se você estiver usando um DataContractSerializer para o Xml Formatter ou JSON Formatter, precisará se livrar dele. Eu tinha isso no meu arquivo WebApiConfig:
Simplesmente comento
jsonFormatter.UseDataContractJsonSerializer = true;
e meu parâmetro de entrada não é mais nulo. Agradeço ao 'Despertar' por me dar uma pista.fonte
Se você tem certeza sobre o JSON enviado, deve rastrear sua API com cuidado:
Microsoft.AspNet.WebApi.Tracing
pacoteconfig.EnableSystemDiagnosticsTracing();
aWebApiConfig
classe dentro doRegister
método.Agora olhe para a saída Debug e você provavelmente encontrará um inválido
ModelState
entrada de log .Se
ModelState
for inválido, você poderá encontrar a causa real emErrors
:Ninguém pode adivinhar essa exceção:
fonte
Eu tive o mesmo problema de obter nulo como parâmetro, mas estava relacionado a objetos grandes. Acabou que o problema estava relacionado ao comprimento máximo do IIS. Pode ser configurado em web.config.
Gostaria de saber por que a API da Web suprimiu o erro e envia objetos nulos para minhas APIs. Encontrei o erro usando o Microsoft.AspNet.WebApi.Tracing.
fonte
JSON.stringify (...) resolveu meus problemas
fonte
Sei que essa não é uma resposta para essa pergunta, mas me deparei com ela ao procurar uma solução para o meu problema.
No meu caso, o tipo complexo não estava sendo vinculado, mas eu não estava fazendo um POST, estava fazendo um GET com parâmetros de string de consulta. A solução foi adicionar [FromUri] ao argumento:
fonte
Eu tive o mesmo problema no Fiddler. Eu já tive
Content-Type: application/json; charset=utf-8
ouContent-Type: application/json
no cabeçalho da solicitação.Meu corpo pedido também foi uma string simples, e em Fiddler eu tinha escrito:
{'controller':'ctrl'}
. Isso fez com que o parâmetro string no meu método POST fossenull
.Correção : lembre-se de usar aspas, indicando uma string. Ou seja, eu o corrigi escrevendo
"{'controller':'ctrl'}"
. (Nota: ao escrever JSON, certifique-se de usar apóstrofes ou escapar aspas como esta"{\"controller\":\"ctrl\"}"
:).fonte
A maneira mais simples que encontrei para lidar com objetos JSON simples que passo no MVC 6 é obter o tipo de parâmetro post como o NewtonSoft jObject:
fonte
[FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType
) poderia funcionar melhor, pois a verificaçãobodyMediaType == "application.json"
antes da conversão do corpo para o JObject oferece uma oportunidade para alternativas.A melhor solução para mim é o HTTP completo, como abaixo:
e desserializando a sequência para o objeto que você espera no corpo da postagem. Para mim, WS_OpenSession é uma classe que continha sessionid, user e key.
Você pode usar o objeto param e acessar suas propriedades.
Muito, muito eficaz.
Eu disse proveniente deste URL:
http://bizcoder.com/posting-raw-json-to-web-api
fonte
Para tipos complexos, a API da Web tenta ler o valor do corpo da mensagem, usando um formatador de tipo de mídia.
Por favor, verifique se você tem algum
[Serializable]
atributo decorando sua classe de modelo.Remova o atributo para ver se funciona. Isso funcionou para mim.
fonte
Estou um pouco atrasado para a festa, mas qualquer um que tropeçar em um valor NULL passado ao usar um controlador simplesmente adiciona "=" à frente da sua solicitação POST.
O controlador também passou um valor NULL quando usei o application / json Content-Type. Observe o tipo de conteúdo "application / x-www-form-urlencoded" abaixo. O tipo de retorno da API, no entanto, é "application / json".
fonte
não importa que tipo de valor você deseja postar, coloque-o entre aspas para obtê-lo como sequência. Não para tipos complexos.
javascript:
c #:
fonte
Se você colocar a anotação [FromBody] e tiver um objeto Dto como parâmetro no seu método e ainda não conseguir obter os dados, comece a examinar as propriedades e os campos do seu DTO.
Eu tive esse mesmo problema, onde meu DTO estava chegando nulo. Eu achei que o motivo era que uma das propriedades estava apontando para um objeto que não pode ser serializado :( o que faz com que o formatador de mídia falhe na análise dos dados. Portanto, o objeto sempre foi nulo. Espero que ajude outras pessoas também
fonte
Verifique seus tipos de dados. O fichário do modelo dotnet não converterá um float em um número inteiro (e estou assumindo outros conceitos relacionados). Isso fará com que todo o modelo seja rejeitado.
Se você tem json assim:
mas seu modelo c # se parece com isso:
o fichário do modelo rejeitará o modelo e você será nulo.
fonte
Estou muito atrasado para isso, mas estava tendo problemas semelhantes e, depois de um dia analisando muitas respostas aqui e obtendo informações, encontrei a solução mais fácil / leve para retornar um ou mais parâmetros a uma API da Web 2. segue:
Isso pressupõe que você saiba como configurar uma ação / controlador de API da Web com roteamento correto, caso contrário, consulte: https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with -aspnet-web-api / tutorial-seu-primeiro-web-api .
Primeiro, a ação do controlador, esta solução também requer a biblioteca Newtonsoft.Json.
Lado do cliente usando jQuery
O principal problema que encontrei foi garantir que você envie apenas um único parâmetro geral de volta à API da Web e verifique se ele não tem nome apenas o valor
{ '': dataToSend }
caso contrário, seu valor será nulo no lado do servidor.Com isso, você pode enviar um ou vários parâmetros para a API da Web em uma estrutura JSON e não precisa declarar nenhum objeto extra no lado do servidor para manipular dados complexos. O JObject também permite que você itere dinamicamente todos os parâmetros passados, permitindo uma escalabilidade mais fácil caso seus parâmetros sejam alterados ao longo do tempo. Espero que ajude alguém que estava lutando como eu.
fonte
A passagem correta de um único parâmetro no corpo para o WebAPI funciona esse código
$.post(url, { '': productId }
E pegá-lo em ação
[HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)
A chave é usar a palavra mágica 'valor'. Também pode ser int, ou algum tipo primitivo. Não importa as correções de tipo de conteúdo ou cabeçalho, o Mess é que esse código não funciona na ação de pós-mvc.
fonte