I currently have something like this for my route table. Is there a nicer way to handle versioning in WCF Web API or conventional WCF?
RouteTable.Routes.MapServiceRoute<Service1>("1.0/Route1", Config1);
RouteTable.Routes.MapServiceRoute<Service2>("1.0/Route2", Config2);
RouteTable.Routes.MapServiceRoute<Service3>("1.0/Route3", Config3);
RouteTable.Routes.MapServiceRoute<Service4>("1.0/Route4", Config4);
You could do that, but it is very protocol-bound, in this case HTTP. I wonder if there is a way to do that without worrying so much about protocols? Ideally we only want to do it once and not for each transport out there. Luckily there is a way, let me explain.
At the end of the day, your WCF internals should be protocol agnostic. By that I mean by the time a method is invoked on your service, we should not care whether it came by REST, TCP, HTTP or named pipes.
In WCF this is pretty easy and so is versioning. With versioning we can learn much about .NET interface versioning particularly when it has nothing to do with WCF. The idea is that your service should realize:
interface ISomething1 { ... }
Later when a new method or changes are required you should:
interface ISomething2 : ISomething1 { void SomethingNew (...) }
It's then a simple matter to publish your service with 2 endpoints in config, one pointing to ISomething1 and the other to ISomething2.
Related
I'm new in DDD/ Clean Architecture
I'm trying to implement this architecture in a new from scratch application and I feel confused in some points.
I'm trying to make the best choice to not regret it as application will start growing.
Probably my question is a bit stupid, but again i'm new in DDD and trying to make the best choices.
I'm trying to stick to this example https://github.com/ardalis/CleanArchitecture from Ardalis
Here is my model/problem simplified
-ApplicationAggregateRoot
---Application
---Instance
Application has a list of Instance.
Now I have to do an HTTPRequest "/operationA" on the Instance, this can be done by my blazor UI or by my API via controllers.
The result of this HTTP Request "/operationA" will have to be saved in my repository, and do other stuff, so from what I understood here I need an event when I have the HTPP Response something like "OperationAFinishedEvent"
What I don't really know how to figure it out is how should I make this call in my controller/blazor for example.
Should I do (pseudo code):
A)
_repository.GetApplicationById(1).Instances.First(i => i == id).OperationA()
and have some event raised in OperationA() Method of Instance
(something like "OperationASentEvent") which will be wired to a handler that will call _httpClient.OperationA(instance.Url)
Or should I pass by a domain service class for doing the call instead of an event like:
B)
class Controller
{
OperationA(Instance instance)
{
_instanceService.OperationA(instance)
}
}
class InstanceService
{
void OperationA(Instance instance)
{
_httpClient.OperationA(instance.Url);
new OperationAFinishedEvent(instance);
}
}
C) Or call directly
_httpClient.OperationA(instance.Url);
new OperationAFinishedEvent(instance);
from both controller and blazor
Or maybe something else ?
Thank's
It sounds like you have a Blazor client side app as well as a server-side app that you access via an API. So let's address both sides of the app.
In Blazor, you're typically going to minimize application logic and mostly just make calls to the API. So the code required to kick off an operation for an application instance in Blazor should look like this:
var result = await _httpClient.PostAsync(endpointUrl, data);
If that's a long-running process, you might bet back a result that provides you with another endpoint you can query for status. Otherwise the result should just let you know if the process completed successfully or not.
In your API, you will have various endpoints. Normally these endpoints correspond to resources and operations you can take to alter the state of these resources. Your API resources usually correspond to your domain model, but not always 100%. You should generally avoid using HTTP APIs for Remote Procedure Call (RPC) operations, since they're not really designed for that purpose. Instead, think in terms of requests and responses, typically. Imagine you're trying to get your city government to do something, and the way you do that is by filling out a form to hand to a clerk. Then when the action has been completed, they hand you back some more paperwork. The clerk is your API. The papers are your request and response objects. The actual action - the "instance operation" is happening back inside the office where you don't see it as a client, and none of your interactions are with it directly.
So you might have a resource like this:
/Applications/123/Instances/234/PendingOperations
You can list pending operations. You can POST a new operation request. Etc. There might also be a resource for .../CompletedOperations or you might get back an id for your pending operation that you can later use to view its status. The idea is to have an endpoint that represents a noun (a resource) and not a verb (do something).
Hope that helps!
Your domain layer (aggregate root is in there) should only be concerned about their internal state.
The applications layer (where you also use the repository) can call an interface to an other service, using the data from the aggregate root.
The interface is then implemented in a seperate layer.
Now I'm refactoring old WCF and I need redirect some old WCF service requests to new WCF service.
What I do is intercept per old WCF service call use class implement IOperationInvoker. But I not sure how to set the outsputs in the invoke signature as below.
object Invoke(object instance, object[] inputs, out object[] outputs);
Can anyone give me some suggestion?
you can use Routing Service to distribute old request to the new one(filter by action,endpoint and so on), learn more from MSDN about Routing Service.
For my points, it's high degree of coupling if you handle this situation, you should also edit you code and compile again if you need more restructure in the future.
for Routing Service, just update the config file, no change in the old project.
I am trying to get a WCF DataService working with cross domain requests.
I found this on how to get a WCF service to work with CORS:
http://blogs.microsoft.co.il/blogs/idof/archive/2011/07/02/cross-origin-resource-sharing-cors-and-wcf.aspx
I downloaded the sample, but can't get it to work with a DataService. It works with the sample service, but not with my DataService.
This is my very simple WCF DataService:
public class TestService : DataService<DataContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.UseVerboseErrors = true;
config.SetEntitySetAccessRule("Items", EntitySetRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
}
The TestService.svc file:
<%# ServiceHost Language="C#" Factory="WebHttpCors.CorsWebServiceHostFactory, WebHttpCors" Service="MvcApplication1.TestService" %>
The DataContext is also very simple:
public class DataContext : DbContext
{
public DbSet<Item> Items { get; set; }
}
But still, the preflight options request returns with a 501.
Is there something I am missing to get CORS to work with a Dataservice?
If you're using IIS, verify that the ExtensionLess handler is configured to handle the OPTIONS requests.
A few notes unrelated to your direct issue: since CORS is not properly supported, neither the package you found nor any other solutions will be truly satisfactory (you won't be able to easily specify your policies). It's possible to create a professionally-maintained package to do this using WCF inspectors, but I haven't seen any. Instead, I'd like to invite you to vote this up should you agree.
In the meantime, I can only recommend that you integrate any code you find on the web very carefully (as most of it is barely tested). This article may assist you with that. This is not directly related to Data Services, but it's the same WCF tech. Maybe look at the Web API implementation or other projects for inspiration.
Good luck.
PS: In 90% of the situations, you'll also want to forget about solutions involving proxying. In most architectures, it's just horrible and makes very little sense unless your edge backend is designed in a way that somehow would make it seem less kludgy.
Update: Also verify that the implementation you're using actually handles the OPTIONS requests properly. If it passes them through, WCF Data Services will return a 501, and the interceptor might just pass it back through as well even though the headers were set correctly. Since preflight requests don't need a body, a quick and dirty hack would be to pickup these 501s and change them into 200s, but obviously you really want to stop the request from hitting the data service in the first place.
I have around 6 WCF services that I want to host in an MVC application, routing requests to /services/foo to WcfFooService and /services/bar to WcfBarService
I can accomplish IoC with StructureMap within the services and inject my constructor dependencies by using the example that Jimmy Bogard blogged about here:
Jimmy's article is great, but I'm trying to extend it to work with multiple services hosted within the same MVC application. Essentially, the part at the bottom is the part that is causing me a few headaches:
public class StructureMapServiceHostFactory : ServiceHostFactory
{
public StructureMapServiceHostFactory()
{
ObjectFactory.Initialize(x => x.AddRegistry<FooRegistry>());
//var iTriedThisToo = ObjectFactory.Container;
//container.Configure(x => x.[etc]);
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new StructureMapServiceHost(serviceType, baseAddresses);
}
}
With a single WCF service - routing MVC requests to a specific url via the StructureMapServiceHostFactory shown above works brilliantly - but - If (for example) I create a StructureMapServiceHostFactory2 for the /services/bar call, to allow for a different Registry to be used, when the MVC app spins up, it appears to call each factory in turn as it runs through RouteConfig.cs and adds the routes, so ultimately I don't get configured instances that the first ServiceHostFactory should provide.
It doesn't make a difference if I call Initialize(); or attempt to grab the Container property and call Configure on it, either.
Am I on a hiding to nothing with this? The major reason for requiring registry isolation is due to different NHibernate configuration, but I could configure Named instances of SessionFactory and Session for NHibernate purposes and then use a single registry to get around this. In my mind I wanted the WCF service and MVC-hosting to be capable of using their own IoC containers in isolation, which is why I went down this route.
Is there any way that I can accomplish this?
Ok, so it would appear the only person capable of answering this was me, by virtue of a re-think and 're-architecting' the solution so that the problem doesn't exist in the first place.
I now have a capable way of hosting these services and maintaining IoC with StructureMap neatly per service, without any conflicting concerns.
If you find yourself in a similar position with SOA taking over (SOATO?) - taking a step back is a good start ;)
I've got wcf service for wcf straming. I works.
But I must integrate it with our webserice.
is there any way, to have webmethod like this:
[webmethod]
public Stream GetStream(string path)
{
return Iservice.GetStream(path);
}
I service is a class which I copy from WCF service to my asmx.
And is there any way to integrate App.config from wcf with web.config ?
Sorry, no, ASMX web services don't support streaming.
What is the bigger picture here, what are you trying to archieve with this stream?
Like John Saunders already said: Webservices dont support it. This is behaviour by design: Data is serialized into a platform/language independent and human readable xml packet, sent and deserialized on the receiver side. Of course you could go and split up your stream into chunks and send it piece for piece. But it wouldnt really make sense to misuse webservices like that, plus you are adding huge overhead in bandwidth and processing time.