I have the following problem: I have an IDto interface and a Dto base class implementing said interface.
The base class overrides an id and a ManualId which are defined in the HasId base class.
Then I also have an AuthorDto which inherits from the Dto base class.
Now when I try to perform a http request (POST method) to the service, the ManualId does not get transferred to the service correctly even though the JSON string contains the correct ManualId.
Please help.
My IDto interface:
public interface IDto : IHasId
{
IDto CloneData();
}
My dto base class:
public abstract class Dto : HasId, IDto
{
[DataMember]
public override long? Id { get; set; }
[DataMember]
public override Guid ManualId { get; protected set; } = Guid.NewGuid();
public abstract IDto CloneData();
protected bool Equals(Dto other)
{
return base.Equals(other) && Id == other.Id;
}
public override bool Equals(object obj)
{
if(ReferenceEquals(null, obj)) return false;
if(ReferenceEquals(this, obj)) return true;
if(obj.GetType() != GetType()) return false;
return Equals((Dto)obj);
}
public override int GetHashCode()
{
unchecked
{
return(base.GetHashCode() * 397) ^ Id.GetHashCode();
}
}
}
The HasId class:
public abstract class HasId : IHasId
{
public abstract long? Id { get; set; }
public abstract Guid ManualId { get; protected set; }
protected bool Equals(HasId other)
{
return Id == other.Id && ManualId.Equals(other.ManualId);
}
public override bool Equals(object obj)
{
if(ReferenceEquals(null, obj)) return false;
if(ReferenceEquals(this, obj)) return true;
if(obj.GetType() != GetType()) return false;
return Equals((HasId) obj);
}
public override int GetHashCode()
{
unchecked
{
return(Id.GetHashCode() * 397) ^ ManualId.GetHashCode();
}
}
}
The class doing the HttpRequest:
public class HttpHelper
{
private readonly HttpClient _client = new();
public async Task<TResult> GetObject<TResult>(string requestUri)
{
var response = await _client.GetAsync(requestUri);
response.EnsureSuccessStatusCode();
var valueInJsonFormat = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TResult>(valueInJsonFormat);
}
public async Task<TResult> PostObject<T, TResult>(T obj, string requestUri)
{
var json = JsonConvert.SerializeObject(obj);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _client.PostAsync(new Uri(requestUri), data);
if (response.StatusCode != HttpStatusCode.OK)
{
var httpContent =
JsonConvert.DeserializeObject<HttpResponseContent>(await response.Content.ReadAsStringAsync());
try
{
response.EnsureSuccessStatusCode();
}
catch(Exception e)
{
throw new Exception(httpContent?.Detail ?? e.Message, e);
}
}
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TResult>(result);
}
}
This is the JSON-String:
[
{"Author":
{
"Id":1,
"Settings":
{
"Id":1,
"ArchiveXml":false,
"CreatePdfImmediately":false,
"OverwriteExistingXml":false,
"SaveSimilarTopic":false,
"PdfNameTemplate":null,"PdfPath":null,
"ManualId":"624fa6e3-0864-40bf-87c3a7fcaa1421d4"
},
"Name":"Admindef",
"IsAdmin":true,
"PublicKey" : PUBLIC-KEY HERE (removed since its not relevant),
"ManualId":"f15cb1a5-2d66-4ca9-8dc6-1bf5c25bc7f8"},"Operation":0}]
As far as I understand, you are trying to
POSTaJSONstring with aManualIdin it, but in the service, you don't get the sameManualIdas in yourjson.I think the problem is that your method to
settheManualIdisprotected.See here:
Protecting it means it won't be
setfrom the deserialisation.You should use the default get and set pair like here:
See if this fixes your issue?
This change can also be related to your
Dtoclass and yourHasIdclass.If you want to be able to set the property from the JSON but keep it protected in the code, then you should create a constructor with the parameters you want to deserialize.
Deserialisation follows the following principle:
And you need to be sure that in this graph you will end up calling a constructor with parseable parameters.