【问题标题】:How to get object on ASP.NET Web API?如何在 ASP.NET Web API 上获取对象?
【发布时间】:2015-12-16 16:16:07
【问题描述】:

这是我的 Web API,它工作正常,我的意思是当我在浏览器上输入这个 URL 时:

http://localhost:18207/api/values/GetMyClass

我检索到这个结果:

<MyClass>
<A>a</A>
<b>b</b>
</MyClass>

我的代码:

public class MyClass
{
    public MyClass()
    {
        this.A = "a";
        this.b = "b";
    }
    public string A { get; set; }
    public string b { get; set; }
}


public class ValuesController : ApiController
{
    public MyClass GetMyClass()
    {
        return new MyClass();
    }
}

我有另一个控制台应用程序来使用我的 Web API,我想知道, 我怎样才能拥有 MyClass 的复杂或对象类型?

我的控制台上的代码如下,但它返回字符串类型

 static void Main(string[] args)
    {
        var cts = new CancellationTokenSource();
        MainAsync(args, cts.Token).Wait();
    }

    static async Task MainAsync(string[] args, CancellationToken token)
    {
        string baseAddress = "http://localhost:18207/api/values/GetMyClass";

        using (var httpClient = new HttpClient())
        {
            string response = await httpClient.GetStringAsync(baseAddress);
        }
    }

【问题讨论】:

  • @mason 我向我的 WebApiConfig 添加了另一条路由来处理操作名称,它可以找到,但我不知道如何在我的控制台应用程序上获取我的对象

标签: c# asp.net asp.net-web-api asp.net-web-api2


【解决方案1】:

您的响应可能会以JSON 的形式出现在您的控制台应用程序中(您的浏览器将其接收为 XML 的原因是由于不同的 Accept 标头,您可以通过查看 Content Negotiation 了解这一点)。因此,您需要做的是解析 JSON 并将其反序列化到您的对象中。有很多库可以为您做到这一点。

首先确保您的 MyClass 定义在您的 Web API 项目和控制台项目都引用的类库项目中。这允许我们重用类定义,而无需在两个项目中都有单独的副本。

接下来,您需要一个 JSON 解析库。 .NET 中内置了一个,但有一个名为 Json.NET 的第 3 方,这是黄金标准。我的答案将使用那个,因为我更熟悉它。将Newtonsoft.Json 包安装到您的控制台应用程序中。

然后,如下更改您的控制台应用程序:

using Newtonsoft.Json; // at the top of your file

static void Main(string[] args)
{
    var cts = new CancellationTokenSource();
    MainAsync(args, cts.Token).Wait();
}

static async Task MainAsync(string[] args, CancellationToken token)
{
    string baseAddress = "http://localhost:18207/api/values/GetMyClass";

    using (var httpClient = new HttpClient())
    {
        string json = await httpClient.GetStringAsync(baseAddress);
        MyClass instance = JsonConvert.DeserializeObject<MyClass>(json);
    }
}

JsonConvert 类处理 JSON 的序列化和反序列化。反序列化时,我们只是告诉要反序列化到哪个类,它会尝试将 JSON 转换为该类的实例并返回它。

【讨论】:

    【解决方案2】:

    您可以使用方法“GetAsync”,该方法将返回类“HttpResponseMessage”的对象,然后您可以在 Content 属性上调用“ReadAsAsync”。 请看以下代码:

    public class MyClass
    {
        public MyClass()
        {
            this.A = "a";
            this.b = "b";
        }
        public string A { get; set; }
        public string b { get; set; }
    }
    
    static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();
            MainAsync(args, cts.Token).Wait();
        }
    
        static async Task MainAsync(string[] args, CancellationToken token)
        {
            string baseAddress = "http://localhost:18207/api/values/GetMyClass";
    
            using (var httpClient = new HttpClient())
            {
    
                HttpResponseMessage response = await httpClient.GetAsync(baseAddress);
                response.EnsureSuccessStatusCode();
                 MyClass result = await response.Content.ReadAsAsync< MyClass>();
    
            }
        }
    

    【讨论】:

    • ReasAsAsync 来自哪里?我在看the documentation,并没有看到那个方法。它是一种扩展方法吗?在哪个班??
    • mason 有权利,“httpClient”没有“ReadAsAsync”的定义
    • ReadAsAsync 是 HttpContent 对象的方法。这是响应对象的 Content 属性类型,它是 HttpResponseMessage 类的对象。你不会在 HttpClient 中找到。
    【解决方案3】:

    这是端到端的完整解决方案。我们正在托管一个返回 MyClass 的 Web Api,然后我们正在调用 API 并通过控制台应用程序获取格式化为 XML 的数据。

    首先,我们将MyClass 注释为DataContract

    [DataContract]
    public class MyClass
    {
        public MyClass()
        {
            this.A = "a";
            this.b = "b";
        }
        [DataMember]
        public string A { get; set; }
        [DataMember]
        public string b { get; set; }
    }
    

    MyClass Web API:

    [AllowAnonymous]
    public class MyClassController : ApiController
    {
        public MyClass Get()
        {
            return new MyClass();
        }
    }
    

    以及一个使用HttpWebRequest 调用Web Api 的控制台应用程序。

    这是代码(下半部分来自我的原始帖子):

    static void Main(string[] args)
        {
            // this is my Web API Endpoint
            var req = (HttpWebRequest)WebRequest.Create("http://localhost:17512/api/MyClass");
            // default is JSON, but you can request XML
            req.Accept = "application/xml";
            req.ContentType = "application/xml";
    
            var resp = req.GetResponse();
            var sr = new StreamReader(resp.GetResponseStream());
            // read the response stream as Text.
            var xml = sr.ReadToEnd();
            var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml));
    
            // Deserialize
            var ser = new XmlSerializer(typeof(MyClass));
            var instance = (MyClass)ser.Deserialize(ms);
            Console.WriteLine(instance.A);
            Console.WriteLine(instance.b);
    
            var final = Console.ReadLine();
        }
    

    注意:您需要确定是要在两个程序集之间共享对 MyClass 的引用,还是只想在每个项目中拥有代码文件的副本。

    【讨论】:

    • 虽然提供 XML 可能会更好,但最好展示如何从 Web API 请求 XML 然后反序列化该响应,而不是仅仅将其硬编码到类中。
    • 是的,向我们展示了如何从 Web API 请求 XML,然后反序列化该响应
    【解决方案4】:

    您可以在 WebApiConfig.cs 中删除 XML 格式化程序

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Removing XML
            config.Formatters.Remove(config.Formatters.XmlFormatter);
    
            // Allows us to map routes using [Route()] and [RoutePrefix()]
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    

    然后在你的控制器中你会像你的例子一样返回:

    public class ValuesController : ApiController
    {
        public MyClass GetMyClass()
        {
            return new MyClass();
        }
    }
    

    更新 1:我的回答与问题更加一致

    从控制台应用程序发出请求时,您可以使用RestSharp

    var client = new RestClient("http://localhost:18207/");
    
    var request = new RestRequest("api/values/GetMyClass", Method.GET);
    var response = client.Execute<MyClass>(request);  
    if(response.StatusCode == HttpStatusCode.OK)
      var responseData = response.Data;    
    

    当您执行client.Execute&lt;MyClass&gt;(request) 时,它会将响应反序列化为该类的对象。如果字段名称匹配,它应该可以工作。

    【讨论】:

    • 您如何将 JSON 字符串转回客户端上的 MyClass 实例?
    • 执行此操作时,您的客户端结果(如“$.ajax.success”)将已经是一个 JSON 对象。您还可以使用 JSON.parse() 和 JSON.stringify 来处理客户端中的对象。在您的示例中,您的客户会收到如下信息: { A: 'a', B: 'b' }
    • 这仅适用于从 JavaScript 发出 AJAX 请求的情况。在本例中,它是来自 C# 控制台应用程序的 HTTP 请求。重新阅读问题,因为您的答案不适用。
    • 请您尝试这样做(使用RestSharp):var client = new RestClient(http://localhost:18207/); var request = new RestRequest("api/values/GetMyClass", Method.GET); var response = client.Execute&lt;MyClass&gt;(request); //Autentica no FormsAuthentication e armazena o token da Api, acessível por User.Identity.Name if(response.StatusCode == HttpStatusCode.OK) var responseData = response.Data;
    • 这不是我的问题。但是,我要指出,如果您阅读该问题,那里已经有用于从服务器获取 JSON 的代码,并且未使用 RestClient。请重新阅读问题,它是关于如何将生成的 JSON 转换回对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多