I am asking if anyone knows if it is possible to to pass into a Web Api a concrete class that inherits from a abstract class.
For example:
public abstract class A
{
A();
}
public class B : A
{
}
[POST("api/Request/{a}")]
public class Request(A a)
{
}
At present I have looked around and most solutions seem to say that using TypeNameHandling will work.
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
However this is not that case. Also my model is being passed from a console app to the webapi. I have read that I may be able to deserialize the json object and after attempting this a few times I decide this was not going to work.
I have looked into creating a customer model binder however, I do not want to make my application more complex that it has to be. At present I inherit from the abstract class with 3 models but may in the future extend this. As you may note adding custom model binders may require multiple binders unless there is a way of making one binder generic for all types of the abstract class.
To expand on this in my console app I have instantiated class b as such and then passed it to the ObjectContent before posting to my webapi
item = B();
//serialize and post to web api
MediaTypeFormatter formatter;
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
formatter = jsonFormatter;
_content = new ObjectContent<A>(item, formatter);
var response = _client.PostAsync("api/Request", _content).Result;
when the webapi action is called the object is null
If one really wanted to implement what is asked in the question, there is a custom way to do it.
First, create a custom json converter that is inherited from JsonConverter, in it pick a target class and deserialize an instance.
Then, in your WebApiConfig.Register you add your new converter into config.Formatters.JsonFormatter.SerializerSettings.Converters and enjoy this monstrosity in action.
Should you do it? No.
Understanding how to use such API will bring no joy to any new users, documenting this will not be easy, and most importantly - there are no benefits in implementing it this way. If input types are different, then they deserve separate API methods with different URLs. If only few properties are different - make them optional.
Why the example did not work?
The TypeNameHandling is from Json.NET, Web API knows nothing about it, and type information is not part of the JSON spec, so there is no standard way to solve this particular issue.
Please change [POST("api/Request/{a}")] to [POST("api/Request")].
Your parameter comes from body, not from route.
You could use JsonSubTypes converter for this purposes.
It is very useful and simple tool for polymorphic deserialization with usage of Json.NET.
This is possible via the default model binding. check below method.
public abstract class RequestBase
{
public int ID { get; set; }
}
public class MyRequest : RequestBase
{
public string Name { get; set; }
}
[RoutePrefix("api/home")]
public class HomeController : ApiController
{
[HttpPost]
[Route("GetName")]
public IHttpActionResult GetName([FromBody]MyRequest _request)
{
return Ok("Test");
}
}
Related
I know this might be an opinion-based question, but, I'd rather to ask as there might be some design principle for this.
I'm having a .net C# web API application to expose few APIs to retrieve some data from a database. I'm also using mediateR on this project. The APIs, they all get one request object but all of them have exact same properties. Imagine, we have a BaseProduct class from which ProductA, ProductB, and ProductChave been inherited in the domain project. Now, I need to expose APIs to return these three objects to the users. Here's an example of two of the request objects.
With Inheritance:
public abstract class BaseGetProductRequest { // the props here }
public class GetProductARequest : BaseGetProductRequest, IRequest<GetProductAResponse> { }
public class GetProductBRequest : BaseGetProductRequest, IRequest<GetProductBResponse> { }
public class GetProductAResponse { public ProductA[] Products {get; set;} }
Each of the above requests also has its own request handler class.
With using generics: (BaseProduct is a domain object class from which different product types are inherited)
public class GetProductRequest<TProductType> : IRequest<TProductType[]> where TProductType : BaseProductType { // all props in here }
Which will be used like this in an API:
public async Task<ProductA[]> Get([FromRoute] GetProductRequest<ProductA> request) { // API body }
So, the question is: Which one the following would be a better approach to take from a design point of view?
To take the Inheritance approach as above
Or to implement the requests and request handlers using generics so we'll end up with less files
Personally, I would prefer the first approach as I want to literally have separate request objects for each API, this way it looks cleaner to me besides that would be consistent with the rest of the code as well (as not all the request objects can be implemented generically). Besides, if by any chance in the future there is a need to add a type-specific property for a request object, then, our code will be more flexible with that change.
Is there like any specific design guidelines which recommends for example taking one over another? Thanks for your opinions in advance.
Sure the inheritance approach will give your project a higher performance, due to the re-usability of compiled requests
I'm using a custom JsonConverter and JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects to create the required instances during deserialization. The instances are created by resolving the types from an Autofac IOC container. Everything works fine, except...
I have several "core objects" that request a unique Id in the constructor from a service (which is correctly injected into the constructor). When deserializing this should not happen because it is fairly expensive and the Ids will be populated from the Json file anyway once the instance has been created.
Currently, when resolving from within the custom JsonConverter I'm using _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null)); to then - in the called constructor - check for null and act accordingly.
Some people apparently consider multiple constructors worse than a code-smell when using an IOC (which makes me wonder why Autofac offers several features regarding the topic), but in the context of deserialization I think it can make perfect sense.
As far as I can tell Autofac has mechanisms to decide which constructor to use during registration, but not when resolving. My preferred solution would be to add a custom attribute to a constructor (e.g. [CtorForDeserializing]) and use that for deciding. Is that possible?
There are a couple of extension points Autofac has for reflection-based activations but doesn't have well documented yet that may help you out: IConstructorFinder and IConstructorSelector.
IConstructorFinder is used to locate all the available constructors on a type. The core example is the DefaultConstructorFinder which locates only public constructors. If you wanted to, say, hide constructors with particular attributes or start finding internal/private constructors, you could create a custom finder. This really only happens once so you don't get to make runtime choices here.
IConstructorSelector is used to choose, at resolve time, which constructor should be used to instantiate the object. There are a couple of these in core Autofac, but the primary example is the MostParametersConstructorSelector which selects the constructor that has the most available matching parameters at the time. Constructors get found by the IConstructorFinder and then that set of constructors is what is presented to the IConstructorSelector to choose from. This is where you could make more runtime choices since it happens every time the object is resolved.
There are extension methods to help you add your finder/selector to a registration:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
You don't have to customize both things, you can just do one or the other if you want. I'm just showing you the extensions.
Actually Autofac is able to decide which constructor to use both ways - during registration or resolution. For resolution part here is the quote from documentation: "Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container" (see here).
Consider following example.
public interface ISomeService
{
Guid Id { get; }
}
public class SomeService : ISomeService
{
public Guid Id { get; }
public SomeService()
{
Id = Guid.NewGuid();
}
public SomeService(Guid id)
{
Id = id;
}
}
// Startup.cs:
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerLifetimeScope();
// TestController.cs:
[Route("api/[controller]")]
public class TestController : Controller
{
private readonly IComponentContext _context;
public TestController(IComponentContext context)
{
_context = context;
}
[HttpGet]
public IActionResult Get()
{
var service = _context.Resolve<ISomeService>();
return Ok(service.Id);
}
[HttpGet("{id}")]
public IActionResult Get(Guid id)
{
var service = _context.Resolve<ISomeService>(new NamedParameter("id", id));
return Ok(service.Id);
}
}
// GET http://localhost:5000/api/test/e0198f72-6337-4880-b608-68935122cdea
// each and every response will be the same: e0198f72-6337-4880-b608-68935122cdea
// GET http://localhost:5000/api/test
// this way it responds with some random guid each time endpoint is called
Travis Illig sent me in the right direction - thanks!
I ended up implementing a solution around the following details:
Implement custom attributes, e.g.: public class DeserializeCtorAttribute : Attribute { }, which will be used by the (also to be implemented) IConstructorFinder.
Implement an empty generic interface, e.g.: IDeserializable<T>, which will be used for resolving the services/components.
Let relevant component classes implement the interface (MyClass : IDeserializable<MyClass>) and add an extra registration for the component:
_builder.RegisterType<MyClass>().As<IDeserializable<MyClass>>()
.FindConstructorsWith(MyConstructorFinder);
Use the implemented DeserializeCtorAttribute in the desired constructor of MyClass.
Let the JsonConverter create the required instance by calling (MyClass) scope.Resolve(IDeserializable<MyClass>); casting is required, but safe. Due to the registration the instance will be created using the desired constructor.
'm trying to design a system where a class would be defined in a project, be referenced in another and have new functionalities in the latter. Is there a pattern for this?
Context: I have a game that has items in a common project. Both the server and client reference this same project so I can have the item StaffItem in both the server and client, making it easier to serialize and deserialize between the two. The problem is, I can't redefine the StaffItem class in the client, since it will change the server's perspective of this class. I'm trying to find a nice way to add, for instance, the rendering to the client-side view of the class (added code for textures and all that).
I'm almost at the point of giving up and simply putting the rendering code in the common project, and stubbing it for the server. Any pointers (hehe) would be appreciated.
Instead of transferring the actual objects over the wire, you could introduce a DTO class for serializing and deserializing. This decouples the actual implementations on both sides.
If I understand your question right, there are two options you may consider. First one is to use smth similar with decorator pattern:
class StaffItem : IStaffItem {
public int MyProp {get;set;}
public void MyAction() {}
}
class ClientStaffItem : IStaffItem {
private StaffItem _staffItem;
public ClientStaffItem(StaffItem staffItem) {
_staffItem = staffItem;
}
public int MyProp {
get { return _staffItem.MyProp;}
set {_staffItem.MyProp; = value;}
}
public void MyAction() {
_staffItem.MyAction();
}
public void YouClientMethod() {}
}
The other one use inheritance, but determine which fields you need to serialize and how and use attributes or custom serialization settings to mark only properties you need.
Problem
I call different webservices which returns json strings. I parse these strings to custom objects and save them in a "result class" called APIResult. For instance, one webservice returns a list OBJ1, another returns OBJ2, and sometimes two or more objects are returned as well. The result class is returned to the method calling it with the objects and a boolean indicating whether the request was succesful.
This works, but when I have to call many different webservices the class gets ugly. Right now I have 7 properties like OBJ1, OBJ2, List, List and so on. To avoid adding more properties to the APIResult class I want to redesign it to be more flexible, but I'm not sure what is the best approach.
Ideas
Generics seems to be a good idea. I could initialize my class with new APIResult(ObjectType) and then have one or more properties T Data1. Still a bit ugly to have three properties T Data1, T Data2, T Data3. I am also unsure if I can parse the objects from json to a generic type without reflection and if that would slow things down.
Do you have any suggestions?
Separate the result state from the actual data.
As you suggested, generics are a useful tool for this. Create a result state class that encapsulates the success/failure logic and (in the case of success) provides access to the data.
This could look something like this:
public class ApiResult<T>
{
public bool Success { get; }
public T Dto { get; }
public ApiResult(bool success, T dto)
{
Success = success;
Dto = dto;
}
}
Now design the data classes as simple property bags without any logic. Their only purpose is to define what data is returned from a specific web service. Also, do not try to build deep inheritance hierarchies. Adding the same property to two different DTOs is fine.
public class Dto1
{
string PropertyA { get; set; }
string PropertyB { get; set; }
}
public class Dto2
{
string PropertyA { get; set; }
string PropertyC { get; set; }
}
With this, you are now able to define proxies for the web services you call. A proxy interface could look like this:
public interface ISomeServiceProxy
{
ApiResult<Dto1> GetTheThing(string someParam);
}
In the implementation of this interface you will want to use JSON.NET to deserialize the response into a Dto1 and wrap it in a ApiResult.
Also, you probably want to make the proxy use async. I left that out in these examples, converting them is straight-forward.
There are few things to consider here
Do you need an APIResult class? What are you going to do with it? If you have a well documented REST api (say an odata api) then the response is well described and you can verify that the response you get is what you need. Otherwise what are you going to do if it doesn't match?
if you are just going to parse it into your model you might even consider the generic JObject to hold your response. Then you can check for properties/subobjects on this JObject. You could even pass this into the (newtonsoft) json serializer and have the calling method say what it should look like.
what is the business meaning of your response? Result is always a hard name. However if you you have properties like FirstName, LastName, AddressList, etc then it becomes a lot nicer.
I got a ASP.NET MVC controller like this
[Authorize]
public class ObjectController : Controller
{
public ObjectController(IDataService dataService)
{
DataService = dataService;
}
public IDataService DataService { get;set;}
}
The Authorize attribute is defined as "Inherited=true" in the framework. So when i make the next controller:
public class DemoObjectController : ObjectController
{
public DemoObjectController(IDataService dataService)
: base (dataService)
{
DataService = new DemoDataService(DataService);
}
}
It gets the authorize attribute, but i don't want it here. I want the Demo Object controller to be available to everyone, cause it just uses fake data.
I guess I'll implement my own Authorize attribute that don't get inherited, for i can't find any way to remove the attribute from the inherited class.
Since it is marked as inherited, there isn't much you can do in this case (since you don't control the code that is checking for the attribute via reflection). Implementing your own attribute seems the most practical option.
With MVC you can also often achieve the same functionality with overrides (the On* methods), which might be worth looking into.
If a base type requires authorization then all child types ought to require authorization as well. I think that you ought to inherit from a different type but a workaround would be to declare your own AthorizeAttribute that works for this particular instance.