Reputation: 12862
Here is my controller method:
[System.Web.Http.HttpPost]
[System.Web.Http.Route("api/exercise")]
public HttpResponseMessage CreateExercise(ExerciseDto exercise) {
Here are my classes:
public class Exercise {
[Key]
[Required]
public int ExerciseId { get; set; }
[StringLength(300, ErrorMessage = "The value cannot exceed 300 characters. ")]
public string Title { get; set; }
}
[NotMapped]
[Serializable]
public class ExerciseDto : Exercise {
public ExerciseDto(Exercise exercise) {
ExerciseId = exercise.ExerciseId;
Title = exercise.Title;
UserHasExercise = true;
}
public bool UserHasExercise { get; set; }
public List<int> SomeIds { get; set; }
}
If I use type Exercise
in the API controller, the object comes through. I created the DTO to extend the POCO with some more properties, but if I use this ExerciseDto
class, I get null
whenever I send the same data I was sending before. What is happening?
WebAPI Config:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None;
config.Formatters.Remove(config.Formatters.XmlFormatter);
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var enumConverter = new Newtonsoft.Json.Converters.StringEnumConverter();
json.SerializerSettings.Converters.Add(enumConverter);
Update:
My solution for the time being is to scrap the idea of DTOs altogether and just extend the POCO with [NotMapped]
properties:
public class Exercise {
[Key]
[Required]
public int ExerciseId { get; set; }
[StringLength(300, ErrorMessage = "The value cannot exceed 300 characters. ")]
public string Title { get; set; }
[NotMapped]
public bool UserHasExercise { get; set; }
[NotMapped]
public List<int> SomeIds { get; set; }
}
This keeps everything super simple, but I have a feeling it's not a best practice for more complicated models. Am very interested in seeing the proper way to handle this.
Upvotes: 1
Views: 2147
Reputation: 8025
ExerciseDto
needs a parameterless constructor in order for the Post body deserialize properly.
Update: your update is the way I would do it.
Upvotes: 3
Reputation: 10628
I believe the problem is that you've declared ExerciseDto
as [Serializable]
but you're not passing all ExerciseDto
model parameters in your request (you mentioned that you pass the same data as you did for Exercise
). You can either remove the [Serializable]
attribute or, alternatively, add [JsonIgnore]
to your model's UserHasExercise
and SomeIds
parameters. If you're passing the data as xml and not json, then use [IgnoreDataMember]
instead of [JsonIgnore]
.
Upvotes: 0