Hi all,
This is a follow on from the following question I asked yesterday:
Return complex objects with Web API[
^]
Thanks very much to
KornfeldEliyahuPeter[
^] for his help there.
I'm now creating a console application to access the Web Api. I have used
Calling-a-web-api-from-a-net-client[
^] from Microsoft as my template for creating my client but I'm getting an issue when it tries to de-serialise my object.
To save having to jump between questions here is my object structure:
public interface IMyFileInterface
{
string FileName {get;set;}
MyEnum FileType {get;set;
DateTime UploadDate {get;set;}
}
Classes:
[DataContract]
[KnownType(typeof(FooFileModel))]
public class ReturnModel
{
[DataMember]
public string Name {get;set;}
[DataMember]
public List<IMyFileInterface> LatestFiles {get;set;}
}
[DataContract]
public class FooFileModel : IMyFileInterface
{
[DataMember]
string FileName {get;set;}
[DataMember]
MyEnum FileType {get;set;
[DataMember]
DateTime UploadDate {get;set;}
}
My api call is to an address similar to: "http://localhost:12345/API/API/GetReport"
My client code looks like this:
private async Task<UtilitiesReportModel> GetReportModalAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:12345/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> response = client.GetAsync("API/API/GetReport");
if (response.Result.IsSuccessStatusCode)
{
UtilitiesReportModel reportModel = await response.Result.Content.ReadAsAsync<UtilitiesReportModel>();
Debug.WriteLine(reportModel.Name);
Debug.WriteLine(reportModel.LatestUploads.Count);
return reportModel;
}
return null;
}
}
Which is called from my "main" method as follows:
var res = GetReportModalAsync();
res.Wait();
var theRes = res.Result;
However, when res.Wait() triggers I get the following error:
Could not create an instance of type Common.Objects.IMyFileInterface. Type is an interface or abstract class and cannot be instantiated. Path 'LatestUploads[0].SurveyType', line 1, position 220.
(I don't know if it is relevant but SurveyType is a custom enum).
Now I understand what the error says, for some reason when it tries to de-serialise it is trying to create an instance of an interface, as we all know this is impossible. How do I tell it to create an instance of it's original class? When I look at the response from the API call it has the original data type in.
Any help would be appreciated as I would like to be able to code against interfaces and not hard code the classes if I can help it.
When I call the api in a web browser it displays the result in the following XML. (I know the comment has asked for it in JSon).
<ReportModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Common.Objects">
<CurrentMonth i:nil="true"/>
<LastRefresh>0001-01-01T00:00:00</LastRefresh>
<LatestUploads xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:anyType i:type="FooFileModel">
<DateTimeUploaded>2014-12-08T14:23:37.243</DateTimeUploaded>
<FileName>05122014 cleaned for loading.xlsx</FileName>
<NumberOfEntries>76</NumberOfEntries>
<SurveyType>TypeA</SurveyType>
</d2p1:anyType>
<d2p1:anyType i:type="FooFileModel">
<DateTimeUploaded>2014-12-05T12:04:47.877</DateTimeUploaded>
<FileName>04122014 Cleaned for loading.xlsx</FileName>
<NumberOfEntries>5</NumberOfEntries>
<SurveyType>TypeB</SurveyType>
</d2p1:anyType>
<d2p1:anyType i:type="FooFileModel">
<DateTimeUploaded>2014-12-05T12:05:28.14</DateTimeUploaded>
<FileName>04122014 Cleaned for loading.xlsx</FileName>
<NumberOfEntries>6</NumberOfEntries>
<SurveyType>TypeC</SurveyType>
</d2p1:anyType>
</LatestUploads>
<Name>Site1</Name>
</ReportModel>
If I call "response.Result.Content.ReadAsStringAsync();
I get the following out, which I believe is the Json response:
{"$type":"Common.Objects.ReportModel, Common",
"Name":"Site1",
"LatestUploads":[
{"$type":"Common.Objects.FooFileModel, Common",
"SurveyType":2,
"FileName":"08122014 Cleaned for loading.xlsx",
"DateTimeUploaded":"2014-12-09T14:02:36.147",
"NumberOfEntries":69},
{"$type":"Common.Objects.FooFileModel, Common",
"SurveyType":1,
"FileName":"08122014 Cleaned for loading.xlsx",
"DateTimeUploaded":"2014-12-09T14:03:41.11",
"NumberOfEntries":11},
{"$type":"Common.Objects.FooFileModel, Common",
"SurveyType":2,
"FileName":"05122014 cleaned for loading.xlsx",
"DateTimeUploaded":"2014-12-08T14:23:37.243",
"NumberOfEntries":76}],
"CurrentMonth":null,"LastRefresh":"0001-01-01T00:00:00"}