-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strong types vs metadata model #2
Comments
In my mind the ideal result would be something like: [HttpGet("/sample/{id}")]
public Task Handle(HttpRequest request)
{
var vm = request.GetComposedResponseModel<MyStonglyTypedModel>();
//use the strongly typed model
return Task.CompletedTask;
} This could be enabled by injecting something like: interface IViewModelFactory
{
object CreateViewModel(HttpRequest request);
}
class MyStonglyTypedModelFactory : IViewModelFactory
{
[HttpGet("/sample/{id}")]
public object CreateViewModel(HttpRequest request)
{
return new MyStonglyTypedModel();
}
} There are many more things that need to be changed to enable the above, as of now the dynamic view model does too many things that need to be moved to a CompositionContext kind of thing to avoid forcing your model to implement an interface and thus violate SRP. If we can achieve the above another step could be: //this comes from assembly provided by sales
interface ISalesSampleViewModel
{
decimal Price{ get; set; }
}
//this comes from assembly provided by marketing
interface IMarketingSampleViewModel
{
string Description{ get; set; }
}
//this is defined in a branding owned assembly
class MyStonglyTypedModel : ISalesSampleViewModel, IMarketingSampleViewModel
{
//properties here
}
[HttpGet("/sample/{id}")]
public Task Handle(HttpRequest request)
{
var vm = request.GetComposedResponseModel<ISalesSampleViewModel>();
//the sales composition handler knows nothing about the marketing side
return Task.CompletedTask;
} |
@markphillips100 I made (finally) significant progress on this. ServiceComposer/ServiceComposer.AspNetCore#155 Is the first step toward being able to plug-in a completely custom, and strongly typed, view model. For backward compatibility reasons as of now the only and experimental way to plug-in a custom model is by using interfaces only. This is enabled by a new package I’m working on https://github.com/ServiceComposer/ServiceComposer.AspNetCore.TypedViewModel/pull/2 with the new package installed composition handlers looks like the following: //this comes from assembly provided by sales
interface ISalesSampleViewModel
{
decimal Price{ get; set; }
}
//this comes from assembly provided by marketing
interface IMarketingSampleViewModel
{
string Description{ get; set; }
}
[HttpGet("/sample/{id}")]
[TypedViewModel(typeof(ISalesSampleViewModel))]
public Task Handle(HttpRequest request)
{
var vm = request.GetComposedResponseModel<ISalesSampleViewModel>();
//the sales composition handler knows nothing about the marketing side
return Task.CompletedTask;
} There is no need for a class the implements all the interfaces because that class is dynamically generated at runtime thanks to the the same attribute is used by the API generation to provide proper documentation: you can have a preliminary look at how it works in #3 there is still a lot of work to do before being able to use it in production, I’m confident that this is a promising direction. |
I'll take a look as soon as I can @mauroservienti but I really appreciate your efforts here. My first thoughts are whether this approach would also cater for lists of objects where each object is composed from more than one service, via handler and then subscribers as usual? This is the typical "list of orders" use case where each order has some sales data, some finance data, etc. |
This experiment doesn't support complex object graphs (yet, maybe). It's incredibly complex to support whatever the consumer expects to do, especially if the expectation is "whatever C# allows" 😅 I'm working on 1.8.0 that comes with custom view models factories (implementation merged in ServiceComposer/ServiceComposer.AspNetCore#155). Next step is documentation and a couple more things (https://github.com/ServiceComposer/ServiceComposer.AspNetCore/milestone/1). |
I'm leaning towards thinking a strong type model should be used if documentation is required for response types, i.e. try to use as much of the existing MVC metadata modelling as possible. I especially like the idea that other annotation attributes can be leveraged then; DisplayName etc.
If strong type composition can be achieved by ServiceComposer/ServiceComposer.AspNetCore#155 then great.
Is the intention to support setting a viewmodel dynamic property to a given strong-typed value? Like this:
Is it possible to merge lists of strong types too, in cases where a request subscriber wants to add their data to each record?
The text was updated successfully, but these errors were encountered: