I have an issue. My boss has setup a test SOAP web service that he wants use to consume in our API.
Originally we only had one, so it was straight forward enough.
Now we have two and they are on different endpoints, so I created 2 Web References that look like this:
http://ssd-001/tradeportal/webservices.asmx?wsdl
http://ssd-001/testtradeportal/webservices.asmx?wsdl
We are using autofac and I was able to register the service like this:
builder.RegisterType<webServices>().As<webServices>().InstancePerDependency();
I was going to create a factory class to switch between the two, but the issue I have is that even though they are both a webServices class, they are on different name spaces and do not have an interface or anything.
The only thing I could find was that they both inherit from System.Web.Services.Protocols.SoapHttpClientProtocol, but registering that would lose any of the public methods which I need.
Does anyone know or can think of any suggestions that might help me get around this issue?
Basically I want one class to switch between the two depending on if we are live or not, we currently have a flag in a config file for that.
As #Zohar mentioned, the web services are the same; it's just the URL that is different. So I added an entry to my web.config file and then created a factory class like this:
public static class TradePortalFactory
{
public static webServices Create(CormarConfig config) => new webServices { Url = config.TradePortalUrl };
}
Then I could change my autofac register to this:
builder.Register(m => TradePortalFactory.Create(m.Resolve<CormarConfig>())).As<webServices>().InstancePerDependency();
Related
I have a Service Fabric application with one service which is exposed to Internet (GatewayService) through an ASP.NET Web API and a couple of internal services not exposed to the Internet (let's call one of them InternalService). So far, InternalService is also an ASP.NET Web APIs, so InternalService.cs has a CreateServiceInstanceListeners() method which looks like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[] {
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.ConfigureServices((context, services) => { services.AddSingleton(serviceContext); })
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build()))
};
}
The Startup class (in Startup.cs) for InternalService configures some services, such as adding a SQL DbContext to the Dependency Injection system, and of course setting up ASP.NET with AddMvc() etc. I have a couple of ApiControllers which expose the API.
This works, BUT I don't get any real type safety with this, and it generally makes development a bit cumbersome, needing to deserialize the result manually in my GatewayService before manipulating it. So I decided to go with SF's Service Remoting instead, resulting in a CreateServiceInstanceListeners() method which looks like this:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return this.CreateServiceRemotingInstanceListeners();
}
Then I copied all the logic from the controllers into InternalService.cs too, but this lead to an issue: I don't have access to my DbContext anymore, because it was injected into the constructor of the ApiController, instantiated by ASP.NET according to the rules set in the Startup class, which isn't used anymore.
Is there a way for me to use Startup in the same way when using Service Remoting?
Can I separate the API into multiple classes, in the same way as ApiControllers are separated into multiple classes? I feel like having all exposed methods in the same class will be quite a hazzle.
I know this has already an accepted answer, but I want to add my two cents.
As you have realized, remoting has two major differences compared to WebApi:
Given a remoting interface, you have a single implementation class
The remoting implementation class is a singleton, so, even if you use DI as explained in the accepted answer, you still can't inject a DbContext per request.
I can give you some solutions to these problems:
This one is simple: create more interfaces. You can add as many remoting interfaces as you want in a single service fabric service. So, you should split your remoting API into smaller interfaces with groups that make sense (interface segregation). But, I don't think you should have many, because that would probably mean that your microservice has too many responsibilities.
A naive approach to having dependencies per request is to inject factories into the remoting class, so you can resolve and dispose dependencies in every method instead of by constructor injection. But I found a much better approach using Mediatr, which might not seem trivial, but once set up it's very easy to use. The way it works is you create a little helper class that gets an ILifetimeScope (as you use Autofac) in the constructor and it exposes an Execute method. This method will create a child LifetimeScope, resolve Mediatr and send a WrapperRequest<TRequest> (the wrapper is a trick so that the remoting input and output objects don't have to depend on Mediatr). This will allow you to implement a Handler class for each remoting operation, which will be resolved per request so that you can inject the dependencies in the constructor as you do with a WebApi controller.
It might sound confusing if you are not familiar with Mediatr and Autofac. If I have time I'll write a blog post about it.
You can use Autofac, there's an entire page that explains how to set it up:
Add the Autofac.ServiceFabric nuget package
Configure DI:
// Start with the trusty old container builder.
var builder = new ContainerBuilder();
// Register any regular dependencies.
builder.RegisterModule(new LoggerModule(ServiceEventSource.Current.Message));
// Register the Autofac magic for Service Fabric support.
builder.RegisterServiceFabricSupport();
// Register a stateless service...
builder.RegisterStatelessService<DemoStatelessService>("DemoStatelessServiceType");
// ...and/or register a stateful service.
// builder.RegisterStatefulService<DemoStatefulService>("DemoStatefulServiceType");
using (builder.Build())
{
ServiceEventSource.Current.ServiceTypeRegistered(
Process.GetCurrentProcess().Id,
typeof(DemoStatelessService).Name);
// Prevents this host process from terminating so services keep running.
Thread.Sleep(Timeout.Infinite);
}
check out the demo project.
I have a RESTful web service containing hierarchical resources. I want to separate these resources in different services class mapped by a global routing class (global.asax). For example, if I had a resource hierarchy like that:
Book/
Book/{BookID}/Chapters/
Book/{BookID}/Chapters/{ChapterID}/
etc...
I could only map to one class like this:
RouteTable.Routes.Add(new ServiceRoute("Books/", new WebServiceHostFactory()
, typeof(BookService)));
This works, but I have to implement all the methods in that single service. I'd much rather have multiple service class like BookService, ChapterService, etc... like this:
RouteTable.Routes.Add(new ServiceRoute("Books/", new WebServiceHostFactory()
, typeof(BookService)));
RouteTable.Routes.Add(new ServiceRoute("Books/{BookID}/Chapters/"
, new WebServiceHostFactory(), typeof(ChapterService)));
But it doesn't work... So right now I am forced to have all my method defined in a single service. Is there a way around that or am I doomed to use this single huge service class ?
Take a look at this answer. It has to do with routing using the ASP.NET Web API (which some comments suggested using and I would also), but it also relates to developing RESTful API's in general. I would not try to show the hierarchy of your schema in the API as I think it adds to much unneeded complexity. So an example for your API would look something like this:
/Chapters/{ChapterID}?Book={BookID}
This eliminates complex routing, is easier for API users to understand, and sticks with RESTful principles.
I am writing a dll that is referencing to some WCF service.
The dll is functioning as a Gateway of the service and all calls are going through it.
Probably there can be concurrent calls .
I have referenced the service but now I cannot decide how to write the wrapper functions correctly.
Is there some example or best practice for this functionality.
I would make wrapper that matches the web service interface. It would also be a good idea to wrap up all of the objects exposed. Basically create a proxy. What I find really useful for this type of thing is to create an interface that matches the API and implement that. That way, you can create a dummy version of the DLL for testing without the overhead (or potential costs) associated with the WCF call. It would also make it much simpler if you need to replace the WCF call with an alternate provider in the future.
As an example, lets assume that we have an WCF service to an external provider for processing a payment. Something like this:
void ProcessPayment(float amount);
We could easily hook this into our code. The problem is that a simple change to the interface would result in us having to make changes everywhere the code is referenced. The same would be necessary if we changed providers to someone else, even if the interface was almost identical. Adding something like a simple interface:
interface IPaymentProvider
{
void ProcessPayment(float amount);
}
Would completely decouple our code from the WCF service. We could easily build a class like this:
class PaymentProviderAWrapper : IPaymentProvider
{
void ProcessPayment()
{
// Call the WCF service
}
}
That we could load dynamically with a factory or dependency injection framework like Spring.NET. Changing to a provider B would be as simple as creating a new wrapper:
class PaymentProviderBWrapper : IPaymentProvider
{
void ProcessPayment()
{
// Call provider B's Native DLL
}
}
Switching your code from provider A to B would be as simple as changing a configuration setting.
Even if we compiled the library directly into our code, all we would need to do is change the construction logic to use the new library. The rest of our application would not change at all. Just a simple recompile.
In response to Graymatter's answer I don't see what the difference is between calling a service wrapper which exposes the same calls and then forwards the calls to the real service, and just calling the service, assuming a one-to-one mapping on individual calls and no change in transport binding.
The only reason you would want to create a wrapper in the first place is that the interface exposed in some way does not meet your requirement on it's own. There are several reasons you may want to do this but a few common ones:
Protocol translation - the service is not exposed across the correct transport binding for your needs
Service Composition - the interface operations are too granular and don't represent business-level operations.
Authentication - perhaps you require an authentication layer on top of the endpoint you are consuming.
So how to wrap the service endpoint depends on why you want to wrap the service...
I need to create a backing service for a jQuery token input field control.
Our application consists of controls for a (third-party) DotNetNuke module called SimpleWrapper. The way this module works is that it provides a lightweight but not very flexible way of displaying regular ASP.NET user controls on a DNN page. The caveat is these are .ascx controls, not .aspx pages.
I'm mostly at a loss at which of the various technologies available to use. I looked at ASMX services but those mostly seem tailored to producing generated JavaScript proxy code. I need to be able to:
mount the service at a static URL
have it accept a single string parameter
have it produce JSON in a specific, but very simple format
I don't really need strong integration with ASP.NET, like being able to respond to a postback or some such. I'd also prefer something deployable just by adding a file, without having to edit configuration files. What would be a straightforward way to spit out a chunk of JSON in such an environment?
WCF (I think starting with version 3.51) has a nice "zero config" feature that integrates easily with IIS. All you have to do is
create a JSON aware interface & service
create a simple .SVC file in the IIS site.
You don't need to mess with funky .config files :-)
Example .SVC file:
<%# ServiceHost
Service="MyNamespace.MyService"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
Example interface & service implementation, something like this:
public class MyService : IMyService
{
public string Test(string text)
{
return text; // whatever
}
}
[ServiceContractAttribute(Namespace="http://schemas.myservice.com")]
public interface IMyService
{
[OperationContractAttribute]
[WebInvokeAttribute(UriTemplate="Test", // change this accordingly
ResponseFormat=WebMessageFormat.Json, // change this accordingly
RequestFormat=WebMessageFormat.Json, // change this accordingly
BodyStyle=Wrapped)]
string Test(string text);
}
Here is an extra cool link about all this: WCF Web Services The Easy Way.
JSON Exposed thru Restful Service
This Link will guide you step by step on how to do what I believe to be what you are looking for has actual code sample
I don't see why WCF Web services or ASMX Web Services are not suitable for what you say you need. Personally, that's the way I'd go (choosing WCF over ASMX).
I looked at the link DJ KRAZE posted and it uses an HTTP Handler plus uses some third party Javascript serializer (one extra dependency that isn't really needed since you have JavascriptSerializer if needed).
I'm looking for a good way to achieve the following:
I have a web application (MVC 3), with a separate Class Library that contains the back-end logic of a CMS that I'm making. This CMS uses NHibernate to connect to a database. I want the user to be able to configure the connectionstring (and eventually even the flavour of the database) in their web.config file.
What I'm looking for is a good way to get the connection string from the web.config file, even though the DLL is completely separate. Is this possible? Will I have to pass my connection string to my class library somehow? Or will I be able to access it when the application runs?
If I have to create some code in my web application to pass the connection string to my Class Library, how can I make this code as portable as possible, so I won't have to write it again for my next webapp?
Thanks a lot for any ideas you have.
You can pass in the connection string to the classes in the class library from the web site.
This is a better choice than trying to get the information directly from the configuration file, as otherwise you will have a dependency on the configuration file existing with the exact right key (making testing the class somewhat harder).
See this blog post for arguments against accessing configuration directly (which is very commonly done, but is not best practice).
You can access System.Configuration.ConfigurationManager from your class library. That'll give you access to the AppSettings and ConnectionStrings.
I have exactly the same setup with a FOSS project I'm involved with. It contains everything (even the Controllers and Global.asax.cs) in the 'Core' class library.
There's plenty of valid solutions, the one I opted for was to create a Settings class which is essentially a set of static properties, inside which you have:
public static string ConnectionString
{
get { return ConfigurationManager.ConnectionStrings["MYAPP"].ConnectionString; }
}
Note: make sure your class library has System.Configuration added as a reference.
Inside your Application (the class derived from HttpApplication) you pass the settings across, although there is nothing to stop you tighly coupling the NH setup with the settings class:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
SetupNHibernate();
}
public virtual void SetupNHibernate()
{
NHibernateRepository.Current.Configure(RoadkillSettings.DatabaseType, Settings.ConnectionString, false, Settings.CachedEnabled);
}
If this is any use to you, the source is here.
You can use the ConfigurationManager class to access items in your web.config or app.config file. However, in your class library, be sure to take in the key name of any appSettings and/or connectionString settings from the consumer (preferably in the constructor). This avoids the problem of you choosing a key name that the consumer is already using elsewhere.
Since you are using the class library to the MVC web application, it is accessible to the class library also. No additional settings are needed. Even though the class library when built giving a separate dll, it is referenced in the current project. So the connection string will be available to the class library also.
I'd go with something like Autofac to give you some IoC implementation which can store a settings interface for your connection strings. This would allow you to setup the value from the web.config on application start, or to set it within tests to a different value without your Class Library ever having to be coupled to a web.config.
You can add new Existing item from another project to your class library. Then change Build Action to Embedded Resource and Copy to Output Directory to Copy if newer on the Web.config file.
Web.config in another project
<configuration>
<appSettings>
<add key="MyConfigValue" value="Test" />
</appSettings>
</configuration>
Class library test file
var doc = XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web.config"));
var myConfigValue = doc.Element("configuration")
.Element("appSettings")
.Elements("add")
.FirstOrDefault(e => e.Attribute("key").Value == "MyConfigValue").Attribute("value").Value;