【问题标题】:MVC 5 Authentication and HttpClient No MediaTypeFormatter is availableMVC 5 身份验证和 HttpClient 没有可用的 MediaTypeFormatter
【发布时间】:2014-01-08 13:21:49
【问题描述】:

我有一个 MVC 5 Web Api 和一个连接到它的桌面应用程序。

我有一个控制器并从应用程序连接到它没有任何问题,但是当我将 [Authorize] 属性放入控制器时,桌面应用程序中的 httpclient 停止工作并说没有可用的 MediaTypeFormatter。

我认为 HttpClient 工作正常,我尝试使用请求标头定义身份验证: httpClient.DefaultRequestHeaders.Authorization 并使用这种方式httpclient = new HttpClient(new HttpClientHandler { Credentials = new NetworkCredential("UserName", "password") });

在使用 MVC 4 的 pass 中,它适用于身份验证。

在这种情况下,使用 MVC 5,它在使用匿名时可以完美运行,但是当我进行身份验证时,我在 httpresponse.Content.ReadAsAsync 中得到了这个异常

No MediaTypeFormatter is available to read an object of type 'Dictionary`2' from content with media type 'text/html'.

我应该去哪里看?

更新

我将 httpResponse 作为字符串读取,以查看 httpclient 获取的内容,并在字符串中读取登录页面的 HTML。 Aparently 身份验证失败,MVC + API 重定向到登录页面。 我现在该怎么办? 为什么身份验证不像以前的 MVC 4 Web API 那样工作?是因为新的OWIN认证吗?

【问题讨论】:

  • 根据您在帖子中提到的详细信息,看起来服务器正在响应错误,可能与 html 文档中的详细信息有关,这就是响应内容类型为 text/html 的原因。默认情况下,Web API 附带jsonxmlformurlencoded 的格式化程序,ReadAsAync 也只能理解这些格式...试试这个..do httpresponse.Content.ReadAsStringAsync().Result 以获取 html 并检查您看到的错误..
  • @KiranChalla 你太棒了!我根据您的建议更新我的答案
  • 您是否在进行身份验证时存储cookie,并在需要进行身份验证时将其传递给服务器?

标签: c# asp.net-mvc authentication asp.net-web-api asp.net-mvc-5


【解决方案1】:

试试:

httpClient.Accept = "text/html,application/xhtml+xml,application/json";

【讨论】:

  • 我没有从网络服务器读取字符串。我正在阅读字典或对象...
  • 我添加了 httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))。仍然没有 MediaTypeFormatter 可用于从媒体类型为“text/html”的内容中读取类型为“Dictionary`2”的对象。在 Web Api 中默认返回 JSON。
【解决方案2】:

这些问题是因为身份验证不起作用。 MVC5 使用 Web 窗体身份验证,因此我不得不创建一种新的方式来验证 HttpClient。

  • 访问 /Account/Login 页面并阅读 _RequestVerificationToken
  • 将用户名、密码和 _RequestVerificationToken 发布到 /Account/Login

错误是因为,当身份验证失败时,MVC5 将 HttpClient 重定向到登录页面。所以我没有得到 JSON,我得到的是 HTML。登录页面的 HTML。

【讨论】:

    【解决方案3】:

    这篇文章应该会有所帮助。

    http://www.asp.net/web-api/overview/security/basic-authentication

    它告诉我们需要为 Web API 实现身份验证处理程序。

    而且我认为 Web API 在 VS2013 中是一个独立的项目类型,请确保您没有使用默认使用表单身份验证的 MVC。

    如果你必须使用整个 MVC 包,那么你必须像 Ricardo Polo 所说的那样在登录页面上发布一个 http 帖子,然后将你得到的 cookie 附加到每个 api 调用。例如:

    HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create(string.Format("https://{0}/login", server));
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    
    bool loginSuccess = false;
    
    if (response.StatusCode == HttpStatusCode.OK)
    {
        //If there's a cookie in the response, it means login successful, 
        //and the cookie is the one returned by the server that can be used to identify
        //the client when calling Authorized api calls.
        loginSuccess = (response.Cookies.Count > 0);
    }
    response.Close();
    
    //Now make a request to the api
    HttpWebRequest ApiRequest = (HttpWebRequest)System.Net.WebRequest.Create(string.Format("https://{0}/api/values", server));
    ApiRequest.CookieContainer = new CookieContainer();
    ApiRequest.CookieContainer.Add(response.Cookies[0]);
    //From here add code to get the response.
    

    上面的代码可以使用HttpClient来完成。

    【讨论】:

      【解决方案4】:

      当我的 Action 输入参数是 Dictionary 时,我遇到了这样的异常,我通过创建包含所有输入参数和 Dictionary 的自定义模型来解决它,然后它就可以工作了

      【讨论】:

        【解决方案5】:

        Visual Studio 中的 MVC 5 Web API (Web API 2) 模板使用基于令牌的 OWIN 中间件进行身份验证。

        阅读以下文章:

        验证并获取承载令牌 http://www.asp.net/vnext/overview/authentication/individual-accounts-in-aspnet-web-api

        In the Fiddler Composer tab, enter the following URL (remember to change "port" to the actual port number):
        
        http://localhost:port/Token
        
        Leave the request method as POST. Change the Content-Type header to application/x-www-form-urlencoded. Replace the request body with the following:
        
        grant_type=password&username=Alice&password=password123
        
        Click Execute to send the request. Here is the raw HTTP request:
        
        POST http://localhost:49436/Token HTTP/1.1
        User-Agent: Fiddler
        Host: localhost:49436
        Content-Type: application/x-www-form-urlencoded
        Content-Length: 55
        
        grant_type=password&username=Alice&password=password123
        

        在 MVC 5 Web API 模板中,您可以启用基于 cookie 的身份验证,但要获得身份验证,您需要使用 /Token 端点,方法是发送带有三个字段的表单正文的 Http Post 消息 1.grant_type 2.用户名 3.密码.

        响应此消息,您将获得一个 JSON 对象,您可以在其中找到 access_token(如果您不想使用基于 Token 的授权,您可以忽略它)并且如果配置了使用 cookie 身份验证,服务器将设置一个 cookie(默认)。默认情况下,从 ApiControllers 派生的控制器在某些 VS 模板中不使用 cookie 身份验证。您需要存储 access_token 并将其放在对 ApiController 的所有进一步请求的标头中。 Http 标头应该是这样的: Authorization: Bearer [place_accesstoken_without_sorrunding_braces]

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-07-02
          • 1970-01-01
          • 2015-04-20
          • 1970-01-01
          • 2014-03-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多