Assuming there is some service:
public interface IDeviceManagerService
{
ISomeDeviceApi Api { get; }
}
It's purpose is to monitor external environment (USB, network, etc.), instantiate device API when the device detected and make property null when the device is no longer available.
Supposing there is a view model with this service injected, I would like to have change notifications for IDeviceManagerService.Api to make things like below possible (for example, having the button which is only active when the device API is available).
private Boolean OnSomeCommandCanExecute()
{
return _deviceManagerService.Api != null;
}
I wonder if there is a clean way to make this work without manual change notifications handling (with Catel.Fody or PropertyChanged.Fody). So far I have managed to get working result by making service implementation derived from ModelBase, registering it's injected instance as a [Model] inside the view model and exposing it's Api property using [ViewModelToModel] attribute, but this is very dirty way.
Is there some common approach or It would be better to go with implementing INotifyPropertyChanged and use notifications wrapper instead?
In most approaches, services don't implement INotifyPropertyChanged (they are not models), so my recommendation is to add manual events:
public interface IDeviceManagerService
{
ISomeDeviceApi Api { get; }
event EventHandler<DeviceApiEventArgs> ApiChanged;
}
This way you can deal with the stuff you are interested in (subscribe in InitializeAsync, unsubscribe in CloseAsync).
Related
We are moving from an on premise-like application to a multi tenant cloud application.
for my web application we made a very simple interface based on IPlugin, to create a plugin architecture. (customers can have/install different plugins)
public interface IWebPlugin : IPlugin
{
string ContentBaseUrl { set; get; }
}
We have some plugins that would normally be loaded in on startup. Now i'm migrating the code to load at the beginning of a request (the Register function is called on request start), and scope everything inside this request.
It's not ideal but it would bring the least impact on the plugin system for now.
I could scope the Container by making an AppHost child container which would stick to the request:
Container IHasContainer.Container
{
get
{
if (HasStarted)
return ChildContainer;
return base.Container;
}
}
public Container ChildContainer
{
get { return HttpContext.Current.Items.GetOrAdd<Container>("ChildContainer", c => Container.CreateChildContainer()); }
}
problem case
Now im trying to make plugins work that actually add API services.
appHost.Routes.Add<GetTranslations>("/Localizations/translations", ApplyTo.Get);
But this service is unreachable (and not visible in metadata). How do i make it reachable?
I see you execute the following in ServiceController AfterInit. Re-executing this still wouldnt make it work.
//Copied from servicestack repo
public void AfterInit()
{
//Register any routes configured on Metadata.Routes
foreach (var restPath in appHost.RestPaths)
{
RegisterRestPath(restPath);
//Auto add Route Attributes so they're available in T.ToUrl() extension methods
restPath.RequestType
.AddAttributes(new RouteAttribute(restPath.Path, restPath.AllowedVerbs)
{
Priority = restPath.Priority,
Summary = restPath.Summary,
Notes = restPath.Notes,
});
}
//Sync the RestPaths collections
appHost.RestPaths.Clear();
appHost.RestPaths.AddRange(RestPathMap.Values.SelectMany(x => x));
appHost.Metadata.AfterInit();
}
solution directions
Is there a way i could override the route finding? like extending RestHandler.FindMatchingRestPath(httpMethod, pathInfo, out contentType);
Or could i restart the path compilation/caching? (would be enough for now that the service would be reachable tenant wide )
All configuration in ServiceStack should be contained within AppHost.Configure() and remain immutable thereafter. It's not ThreadSafe to modify ServiceStack's Static Configuration at runtime like trying to modify registered routes or Service Metadata which needs to be registered once at StartUp in AppHost.Configure().
It looks as though you'll need to re-architect your solution so all Routes are registered on Startup. If it helps Plugins can implement IPreInitPlugin and IPostInitPlugin interfaces to execute custom logic before and after Plugins are registered. They can also register a appHost.AfterInitCallbacks to register custom logic after ServiceStack's AppHost has been initialized.
Not sure if it's applicable but at runtime you can "hi-jack Requests" in ServiceStack by registering a RawHttpHandler or a PreRequestFilter, e.g:
appHost.RawHttpHandlers.Add(httpReq =>
MyShouldHandleThisRoute(httpReq.PathInfo)
? new CustomActionHandler((req, res) => {
//Handle Route
});
: null);
Simple answer seems to be, no. The framework wasn't build to be a run-time plugable system.
You will have to make this architecture yourself on top of ServiceStack.
Routing solution
To make it route to these run-time loaded services/routes it is needed to make your own implementation.
The ServiceStack.HttpHandlerFactory checks if a route exist (one that is registered on init). so here is where you will have to start extending. The method GetHandlerForPathInfo checks if it can find the (service)route and otherwise return a NotFoundHandler or StaticFileHandler.
My solution consists of the following code:
string contentType;
var restPath = RestHandler.FindMatchingRestPath(httpMethod, pathInfo, out contentType);
//Added part
if (restPath == null)
restPath = AppHost.Instance.FindPluginServiceForRoute(httpMethod, pathInfo);
//End added part
if (restPath != null)
return new RestHandler { RestPath = restPath, RequestName = restPath.RequestType.GetOperationName(), ResponseContentType = contentType };
technically speaking IAppHost.IServiceRoutes should be the one doing the routing. Probably in the future this will be extensible.
Resolving services
The second problem is resolving the services. After the route has been found and the right Message/Dto Type has been resolved. The IAppHost.ServiceController will attempt to find the right service and make it execute the message.
This class also has init functions which are called on startup to reflect all the services in servicestack. I didn't found a work around yet, but ill by working on it to make it possible in ServiceStack coming weeks.
Current version on nuget its not possible to make it work. I added some extensibility in servicestack to make it +- possible.
Ioc Solution out of the box
For ioc ServiceStack.Funq gives us a solution. Funq allows making child containers where you can register your ioc on. On resolve a child container will, if it can't resolve the interface, ask its parent to resolve it.
Container.CreateChildContainer()
According to MT documentation each bus instance should have a different queue name.
Am I right to assume that following is correct configuration?
What wires the WebApi and Backend queue together?
Consider even more advanced scenario
When I design my backend pipeline to use message processing as well I can later slice it and let it use over the wire transport quite easilly. Question is, can I somehow configure MT so the Azure configured Bus relays the messages to the bus configured with local transport?
I'm going to answer this in the context of MassTransit v3, which supports both Azure Service Bus and RabbitMQ. If you are going to use Azure, I'd highly recommend v3 over the transport for v2.
First, about requests. They should be sent, not published. They are usually commands by nature, and not events. The only reason I see people publishing requests is that they don't have the endpoint address of the service. So knowing the endpoint helps, a lot.
Secondly, in your example, every WebAPI instance should have it's own queue to receive responses, since they are sent back to the requestor. With MT3, every IBus instance has a unique auto-delete queue that is setup for this very purpose, to handle responses from requests.
There is a sample, Sample-RequestResponse, in the MassTransit repository on GitHub, that shows how this is setup with RabbitMQ. It's about the same with Azure Service Bus.
The "fabric" that brings it all together is the virtual host (in RabbitMQ) or the namespace (in ASB). The connections between topics and queues determine how it all works together to form a logical bus.
If somebody is trying to us .NET Core + DI to register multiple busses:
Do NOT use the build in AddBus call
No matter what you do it will never register more than one Bus due
This is because internally it calls TryAddSingleton call
TryAddSingleton only adds a new instance to the DI container if there is no instance registered for the interface yet
Note:
No exception or error is thrown
The solution we use
Since the various interfaces necessary are not generic:
Created generic Wrappers around the built in interfaces
Created an interfaces (used a generic parameters) that uniquely identify each RegisteredBus
When a new Wrapper instance is created, we pass the instance of the built in interface into its constructor
The Wrapper then holds the instance of the built in internal interface in a public property Instance
Instead of injecting eg. IBus, we now inject IBus<MyRegisteredBus>
We then use the Instance property of the wrapper to get access to the built in interface instance and store it for later use (the wrapper plays no role after that)
We would love to not have to use some sort of wrapper with a weird Instance property, but short of the built in interface becoming generic or using something like DynamicProxies we could not come up with a more elegant solution.
Ideas / Feedback is very welcome.
Code
Generic AddBus call (otherwise 100% same signature as built in call):
public static void AddBus<TBusType>(this IServiceCollection services, Func<IServiceProvider, IBusControl> busFactory)
where TBusType : class, IBusType
{
IBusControl<TBusType> BusFactory(IServiceProvider serviceProvider)
{
return new BusControl<TBusType>(busFactory(serviceProvider));
}
services.AddSingleton<IBusControl<TBusType>>(BusFactory);
services.AddSingleton<IBus<TBusType>>(provider => new Bus<TBusType>(provider.GetRequiredService<IBusControl<TBusType>>().Instance));
}
The various interfaces / classes we created to make this happen:
// the only purpose of the interfaces derived from `IBusType` is to uniquely idnetify a registered Bus
public interface IBusType { }
public interface IHosted : IBusType { }
public interface ILocal : IBusType { }
public interface IBusTypeWrapper<TBusType, TInterface>
where TBusType : IBusType
{
public TInterface Instance { get; }
}
public class BusTypeWrapper<TBusType, TInterface> : IBusTypeWrapper<TBusType, TInterface>
where TBusType : IBusType
{
public TInterface Instance { get; }
public BusTypeWrapper(TInterface instance)
{
Instance = instance;
}
}
public interface IBusControl<T> : IBusTypeWrapper<T, IBusControl> where T : IBusType { }
public class BusControl<T> : BusTypeWrapper<T, IBusControl>, IBusControl<T> where T : IBusType
{
public BusControl(IBusControl instance) : base(instance) { }
}
public interface IBus<T> : IBusTypeWrapper<T, IBus> where T : IBusType { }
public class Bus<T> : BusTypeWrapper<T, IBus>, IBus<T> where T : IBusType
{
public Bus(IBus instance) : base(instance) { }
}
public interface ISendEndpointProvider<T> : IBusTypeWrapper<T, ISendEndpointProvider> where T : IBusType { }
public class SendEndpointProvider<T> : BusTypeWrapper<T, ISendEndpointProvider>, ISendEndpointProvider<T> where T : IBusType
{
public SendEndpointProvider(ISendEndpointProvider instance) : base(instance) { }
}
How to register generic ISendEndpointProvider:
services.AddSingleton<ISendEndpointProvider<ILocal>>(provider => new SendEndpointProvider<ILocal>(provider.GetRequiredService<IBusControl<ILocal>>().Instance));
UPDATE
To an IHosted service for each Bus type:
- Create a generic HostedService<BusType> service
- Inject the IBusControl<BusType> in the constructor
- and use the injected instance to start stop the specific bus
Afterwards register a IHostedServicefor each bus type.
services.AddSingleton<IHostedService, HostedService<ILocal>>(); services.AddSingleton<IHostedService, HostedService<IHosted>>();`
I'm curious why the decision was made to couple the Service base class in ServiceStack to data access (via the Db property)? With web services it is very popular to use a Data Repository pattern to fetch the raw data from the database. These data repositories can be used by many services without having to call a service class.
For example, let's say I am supporting a large retail chain that operates across the nation. There are a number of settings that will differ across all stores like tax rates. Each call to one of the web services will need these settings for domain logic. In a repository pattern I would simply create a data access class whose sole responsibility is to return these settings. However in ServiceStack I am exposing these settings as a Service (which it needs to be as well). In my service call the first thing I end up doing is newing up the Setting service and using it inside my other service. Is this the intention? Since the services return an object I have to cast the result to the typed service result.
ServiceStack convenience ADO.NET IDbConnection Db property allows you to quickly create Database driven services (i.e. the most popular kind) without the overhead and boilerplate of creating a repository if preferred. As ServiceStack Services are already testable and the DTO pattern provides a clean endpoint agnostic Web Service interface, there's often not a lot of value in wrapping and proxying "one-off" data-access into a separate repository.
But at the same time there's nothing forcing you to use the base.Db property, (which has no effect if unused). The Unit Testing Example on the wiki shows an example of using either base.Db or Repository pattern:
public class SimpleService : Service
{
public IRockstarRepository RockstarRepository { get; set; }
public List<Rockstar> Get(FindRockstars request)
{
return request.Aged.HasValue
? Db.Select<Rockstar>(q => q.Age == request.Aged.Value)
: Db.Select<Rockstar>();
}
public RockstarStatus Get(GetStatus request)
{
var rockstar = RockstarRepository.GetByLastName(request.LastName);
if (rockstar == null)
throw HttpError.NotFound("'{0}' is no Rockstar".Fmt(request.LastName));
var status = new RockstarStatus
{
Alive = RockstarRepository.IsAlive(request.LastName)
}.PopulateWith(rockstar); //Populates with matching fields
return status;
}
}
Note: Returning an object or a strong-typed DTO response like RockstarStatus have the same effect in ServiceStack, so if preferred you can return a strong typed response and avoid any casting.
Was wondering if there's a recommended best-practice way of grouping similar services together in what's becoming a larger and larger project. Say that most of my services can be lumped in either dealing with "Pro" data or "Amateur" data (the data goes way beyond a simple flag in a table, the data itself is totally different, from different tables, on the pro or amateur side.
I know I can add routes to my classes...
/pro/service1
/am/service2
It looks like I can put the DTOs in namespaces....
What about the Service.Interface items (Service and Factory classes). Would you put those into namespaces also?
Finally, is there a way for the metadata page to reflect these groupings? I started to go down this road, but all the services listed out in alphabetical order, and you couldn't see the route or namespace differences between service1 and service2.
thank you
If you want, you can split multiple Service implementations across multiple dlls as described on the Modularizing Services wiki.
You can safely group service implementation classes into any nested folder groupings without having any impact to the external services. But changing the namespaces on DTO's can have an effect if your DTO's make use of object, interfaces or abstract classes which emit type info containing full namespaces.
In ServiceStack v4.09+ (now on MyGet) the MetadataFeature includes the ability to customize the ordering of the metadata page, e.g you can reverse the order of the metadata pages with:
var metadata = (MetadataFeature)Plugins.First(x => x is MetadataFeature);
metadata.IndexPageFilter = page => {
page.OperationNames.Sort((x,y) => y.CompareTo(x));
};
Organising your large project:
For a complex service(s) I setup 4 projects in one solution.
AppHost, This takes care of the configuration of the service. (References Model, Service and Types)
Model, This is the database model (Does not reference other projects)
Service, This is the implementation of the service only, not the interfaces or DTOs (References Model and Types)
Types, This includes my Interfaces, DTOs and routes. (Does not reference other projects)
Having a separate Types library allows the distribution to clients, for example for use with the ServiceStack JsonServiceClient.
Yes you can namespace the Interfaces, DTOs and factory classes, any way you want. They will work as long as they are referenced in your service correctly.
If you are trying to separate more than one service, you should consider separating your service code into logical folders within the Service project. i.e.
/Service/Pro
/Service/Amateur
Wrap the outer code of your Service methods in a public partial static class MyServiceStackApplication, with an appropriate name. Then reference this as the assembly in the AppHost constructor. So for example:
Pro Service (Service Project/Pro/UserActions.cs)
public partial static class MyServiceStackApplication
{
public partial class Pro
{
public class UserActionsService : Service
{
public User Get(GetUserRequest request)
{
}
}
// ...
}
}
Pro Service (Service Project/Pro/OtherActions.cs)
public partial static class MyServiceStackApplication
{
public partial class Pro
{
public class OtherActionsService : Service
{
public Other Get(GetOtherRequest request)
{
}
}
// ...
}
}
Amateur Service (Service Project/Am/UserActions.cs)
public partial static class MyServiceStackApplication
{
public partial class Amateur
{
public class UserActionsService : Service
{
public User Get(GetUserRequest request)
{
}
}
// ...
}
}
etc.
You can see from the above code we can have multiple files, all separated out and organised, but one assembly for ServiceStack to reference in the AppHost:
public AppHost() : base("Pro & Amateur Services", typeof(MyServiceStackApplication).Assembly) {}
Using the reference to the MyServiceStackApplication assembly, and using the partial keyword allows you to organise the code into manageable groupings.
Metadata:
Unfortunately separating the metadata by namespace isn't supported. You could try and customize the MetaDataFeature yourself, but it does seem like a useful feature, being able to separate multiple services where they are hosted in the one ServiceStack application. I would suggest you raise a feature request.
Mythz is bringing out features faster than lightning. :) Seems like he has that covered in the next release and you should be able to apply a custom filter to HostContext.Metadata.OperationNamesMap.
I am designing a system using domain driven design concepts and I am struggling with a few things. The "domain" is essentially a business system for the company I work for. I am also using dependency injection. So, in my model I have things related to any typical business system (Employee, Order, Invoice, Deposit, etc..). Right now I am trying to create a cash posting application in which users (aka Employees) can create deposits and apply them to unpaid invoices. The problem that I am having is that we are also using an external business system (Microsoft Dynamics Nav) to handle our accounting transactions. So essentially I am dealing with two different databases. So, for the cash posting application I have modeled the domain objects Deposit and DepositLine. I also have in my domain an IDepositRepository interface that is responsible for persisting the deposits. To get a deposit from the system I just want to grab it directly from the database. However, in order to create a deposit I have to use the Dynamics Nav web services because there is certain logic that gets executed behind the scenes that I don't know about. I started looking at the concept of an Anti Corruption layer in which I could translate my version of the deposit object into a deposit object suitable for the web service. So here is what I am envisioning right now:
Domain Layer
- Models
- Deposit
- DepositLine
- Repositories
- IDepositRepository
Infrastructure Layer
- Data
- Repositories
- DepositRepository
- DynamicsNav
- Services
- INavCashManagementService
- Translators
- IDepositTranslator
- Adapters
- INavAdapter
Now I thought i might implement the DepositRepository like so:
public class DepositRepository
{
private INavCashManagementService navCashManagementService;
public DepositRepository(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public Deposit GetDeposit(int id)
{
// use nhibernate to get directly from the database
}
public void SaveDeposit(Deposit deposit)
{
this.navCashManagementService.CreateDeposit(deposit);
}
}
First of all, is this an appropriate design? My next problem is that users are also going to have to "Post" deposits. The Nav web services will also have to be used to run the posting routine. But, this is more of a business process rather than a persistence issue, so I don't see it fitting into the repository. So I am wondering how/where I should call the posting routine. Should I create a domain service like this:
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
public CashPostingDomainService(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
}
}
One confusion I have with domain driven design is external dependencies. Doesn't the CashPostingDomainService class now have an external dependency on Nav? I know the implementation isn't in the domain layer, but doesn't the interface itself make it a dependency? The same goes with other technical concerns like sending emails. If I have an IEmailService interface and want to send an email once the deposits are posted, would I inject the interface into the CashPostingDomainService class? Or would that be part of the application workflow? So which one of these options make the most sense (if any):
1
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
private IEmailService emailService;
public DepositController(
ICashPostingDomainService cashPostingDomainService,
IEmailService emailService)
{
this.cashPostingDomainService = cashPostingDomainService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
2
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
public DepositController(
ICashPostingDomainService cashPostingDomainService)
{
this.cashPostingDomainService = cashPostingDomainService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
}
}
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
private IEmailService emailService;
public CashPostingDomainService(
INavCashManagementService navCashManagementService,
IEmailService emailService)
{
this.navCashManagementService = navCashManagementService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
Thanks for the help!
is this an appropriate design?
It seems fine to me. The important thing is for your Repository to stay oblivious of the Nav side of things and let the anticorruption layer handle that. You might want to have a look here for a similar example.
I know the implementation isn't in the domain layer, but doesn't the
interface itself make it a dependency?
You may have that feeling because the name of your (supposedly agnostic) service interface contains "Nav". To reflect a service abstraction that could have Nav or any other ERP as an implementation, you should rename it to ICashManagementService.
If I have an IEmailService interface and want to send an email once
the deposits are posted, would I inject the interface into the
CashPostingDomainService class? Or would that be part of the
application workflow?
It's your architectural decision to choose one or the other.
Option 1. means that sending an email is an intrinsic part of the deposit posting domain operation. If you take your domain module and reuse it in another application, posting deposits will automatically result in sending an email whatever that application is about. This might be the right thing to do in your context, or you might want to make things a little more generic (like, sending feedback after the operation but not deciding in the domain service whether this feedback should be mail, a log file, etc.)
Option 2. means that the sequence of events that happen after posting the deposits is application specific, that is at the use case level rather than business/domain level. It is up to the Controller (or Application Service) to decide which actions to take -send an email or anything else. Consequently, different applications based around your domain layer could decide to take different actions. This also means possible code duplication between these applications if several of them chose to send mails.