Reputation: 5645
This is my Web API and it works fine, I mean when i enter this URL on my browser:
http://localhost:18207/api/values/GetMyClass
I retrieve this result:
<MyClass>
<A>a</A>
<b>b</b>
</MyClass>
My codes:
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();
}
}
I have another console application to use my Web API and want to know, How can i have a complex or object type of MyClass?
Codes on my Console are below but it returns string type
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);
}
}
Upvotes: 5
Views: 16177
Reputation: 14
You could just remove XML Formatter inside your WebApiConfig.cs
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 }
);
}
}
Then in your controller you would return just like in your example:
public class ValuesController : ApiController
{
public MyClass GetMyClass()
{
return new MyClass();
}
}
UPDATE 1: I did my answer become more consistent with the question
When making a Request from a Console Application, you could use 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;
When you execute client.Execute<MyClass>(request)
it will deserialize the response into an object of that class. If field names match it should work.
Upvotes: -1
Reputation: 10390
Here is the full solution end-to-end. We are hosting a Web Api that returns MyClass
and then we are calling the API and getting data formatted as XML through a console application.
First, we have MyClass
annotated as a 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; }
}
The MyClass
Web API:
[AllowAnonymous]
public class MyClassController : ApiController
{
public MyClass Get()
{
return new MyClass();
}
}
and a Console app that uses HttpWebRequest
to call the Web Api.
Here's that code (the bottom half is from my original post):
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();
}
NOTE: You'll need to figure out if you want to share a reference to MyClass
between the two assemblies or if you just want to have a copy of the code file in each project.
Upvotes: 0
Reputation: 29
You can use method "GetAsync" which will return object of class "HttpResponseMessage" and then you can call "ReadAsAsync" on Content property. Please see below code:
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>();
}
}
Upvotes: 0
Reputation: 32694
Your response is probably coming to your console application as JSON (the reason your browser receives it as XML is because of different Accept headers, you can learn about that if you look at Content Negotiation). So what you need to do is parse the JSON and have it deserialize it into your object. There's quite a few libraries that can do that for you.
First make sure that your MyClass
is defined in a Class Library project that both your Web API project and your Console project are referencing. This allows us to reuse the class definition without needing to have a separate copy in both projects.
Next, you need a JSON parsing library. There's one built into .NET, but there's a 3rd party one called Json.NET that is the gold standard. My answer will use that one since I'm more familiar with it. Install the Newtonsoft.Json package into your console app.
Then, change your console app as follows:
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);
}
}
The JsonConvert
class handles serializing and deserializing the JSON. When deserializing, we just tell is which class to deserialize to and it will attempt to convert the JSON to an instance of that class and return it.
Upvotes: 8