【问题标题】:HttpClient - System.Net.Http.UnsupportedMediaTypeException - Server StatusCode 500HttpClient - System.Net.Http.UnsupportedMediaTypeException - 服务器状态码 500
【发布时间】:2014-05-30 14:38:09
【问题描述】:

这是我的 WCF 服务合同,方法信号之一:

[WebInvoke(UriTemplate = "", Method = "POST")]
public InventoryResponse Post(InventoryRequest inventoryRequest)
{

当我向那个端点发出 POST 请求时,这个 REST 端点在提琴手中工作,我确实成功地取回了 json:

我要发布到的端点:http://localhost/Inventory/

标题:

但是这并没有,它正在尝试调用相同的 url。我最终在响应中返回了 500 个服务器端错误,说“内部服务器错误”,这可能意味着某些代码失败了,但是提琴手调用是如何工作的......似乎这并没有加起来。

    using (var client = new HttpClient())
    {
        var postUri= "http://localhost/Inventory/";
        client.BaseAddress = new Uri(postUri);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        inventoryResponse = client.PostAsJsonAsync("", inventoryRequest).Result.Content.ReadAsAsync<InventoryResponse>().Result;

    }

此错误表示我认为我没有从服务中获取 json 对象:

    System.Net.Http.UnsupportedMediaTypeException: No MediaTypeFormatter is available to read an object of type 'InventoryResponse' from content with media type 'text/html'.

System.AggregateException: One or more errors occurred. ---> System.Runtime.Serialization.SerializationException: Error in line 1 position 70. Expecting element 'InventoryPostResponse' from namespace 'http://schemas.datacontract.org/2004/07/EventInventory.Applications.WebService.Jetson.Responses.BulkPosting'.. Encountered 'Element'  with name 'Fault', namespace 'http://schemas.microsoft.com/ws/2005/05/envelope/none'. 

【问题讨论】:

  • 为什么不使用 Fiddler 检查实际发送到服务器的内容?我猜你只是有一个错误页面作为回报,它有 text/html 媒体类型。
  • 我刚刚给你看了
  • 您显示的是 Fiddler Composer,而不是实际请求。
  • 好的,我刚刚发布了请求和响应头信息
  • 我认为存在误解。你说你得到了500 Internal Server Error,但是向我们展示了一个成功的调用(据我所知)使用 Fiddler 本身。为什么不捕获您的HttpClient 生成的流量?还是有什么不允许你这样做?

标签: c# .net json wcf asp.net-web-api


【解决方案1】:

编辑 1:

这似乎是 HTTPClient 的一些限制。我终于为我解决了一个问题。这是我的建议:

  1. 在您的服务合同中更改您的 UriTemplate:

    [WebInvoke(UriTemplate = "Inventory", Method = "POST")]
    public InventoryResponse Post(InventoryRequest inventoryRequest)
    
  2. 将端点地址更改为

    http://localhost
    
  3. 尝试再次使用 HTTPClient 访问服务:

    using (var client = new HttpClient())
    {
        var postUri= "http://localhost/";
        client.BaseAddress = new Uri(postUri);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
        inventoryResponse = client.PostAsJsonAsync("Inventory", inventoryRequest).Result.Content.ReadAsAsync<InventoryResponse>().Result;
    
    }
    

最后,它应该可以工作了。

上一页。答案:

您的客户端没有发送正确的请求,服务器需要 xml 但客户端发送其他内容(似乎它是 json 并且内容类型是文本)。

  1. 您可以在客户端上进行一些不同的调用: 在您的客户端库中仅使用服务接口和数据合同进行参考(不应该有服务实现,但如果用于测试也可以)。并用以下代码替换您的代码:

    ChannelFactory<YourServiceInterface> myChannelFactory = new ChannelFactory<YourServiceInterface>("MyService"); //MyServive clinet endpoint name
    
    // Create a channel.
    YourServiceInterface wcfClient1 = myChannelFactory.CreateChannel();
    var resp = wcfClient1.Post(inventoryRequest);
    
    ((IClientChannel)wcfClient1).Close();
    

    如果您关心异步操作,您可以使用 TPL 来完成,使用任务

  2. Fiddler 可以选择捕获来自其他客户端的每个请求。这样做并向我们发送请求和响应的内容。

  3. 您的客户肯定有问题。你可以试试这个代码,它必须有效(它对我有用,我已经检查过):

    public class WebRequestor
    {
        public void MakeCall(DividendEvents dividends, Uri uri)
        {
            var postData = Serialize(dividends);
            var request = FormWebRequest(postData, uri);
    
            var response = request.GetResponse();
    
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);
            var dataStream = response.GetResponseStream();
            var reader = new StreamReader(dataStream);
    
            // Read the content of response, if you need to have to deserialize it (in the same way as Serialize method does serialization)
            string responseFromServer = reader.ReadToEnd();
    
            reader.Close();
            dataStream.Close();
            response.Close();
        }
    
        private static WebRequest FormWebRequest(string postData, Uri uri)
        {
            WebRequest request = WebRequest.Create(uri);
            request.Method = "POST";
            request.ContentType = "application/json";
    
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            request.ContentLength = byteArray.Length;
            // Get the request stream.
            Stream dataStream = request.GetRequestStream();
            // Write the data to the request stream.
            dataStream.Write(byteArray, 0, byteArray.Length);
            // Close the Stream object.
            dataStream.Close();
            return request;
        }
    
        private static string Serialize(object data)
        {
            var stream1 = new MemoryStream();
            var testSer = new DataContractJsonSerializer(data.GetType());
            testSer.WriteObject(stream1, data);
            stream1.Seek(0, SeekOrigin.Begin);
            var sreader = new StreamReader(stream1);
            var cont = sreader.ReadToEnd();
            return cont;
        }
    }
    

这是实际的调用:

        var div = new DividendEvents() {Events = new[] {1, 2, 3}, Id = "GOOGL"};
        new WebRequestor().MakeCall(div, new Uri("http://localhost:9002/Pricing/Dividends"));

【讨论】:

  • 不,服务器需要 json,我通过能够在 fiddler 中发送 json 来证明这一点,我们一直在允许 json
  • 不,我正在进行 REST 调用,我不是那样做的。使用 HttpClient 的全部意义在于模拟集成测试,即用户对服务端点进行 REST 调用
  • 调查对象 var responseRes = inventoryResponse = client.PostAsJsonAsync("", inventoryRequest).Result;它会告诉你更多关于错误的信息,发布它所说的一切。
  • 这就是我一直在做的事情,但是使用 httpclient,我查看了请求和响应属性并进行了广泛的检查,发现没有什么不同
  • 服务器端有错误处理程序吗? :stackoverflow.com/a/23069307/3523746
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 2018-02-19
  • 2020-03-11
  • 2021-10-28
相关资源
最近更新 更多