Design Pattern for Creating API URL - c#

I am building a class library that interacts with various 3rd party API's. I have used an facade pattern to provide simplified access to complicated and confusing calls, and a factory pattern to return the correct implementation. I am now trying to build one of the implementation but cant think of an elegant design.
The implementation i am building requires a URL to be constructed (which i am doing via URIBuilder). I then need to "execute" the url. I then deserialize the Xml result into a class.
I am planning on using HttpClient to call the api with the URI i built, but am not sure on how to structure the class. The options i have thought of are:
A base class of my implementation so can call it via base.InvokeURI(Uri myUri).
A seperation class so it can be used by multiple implementations
I am also unsure where the deserialization should reside.

I think using Interface in this case is more suitable:
public interface IURLInvoke
{
string InvokeURI(Uri myUri);
}
// some implementation
public class YourURLInvoker: IURLInvoke
{
public string InvokeURI(Uri myUri)
{
// do something
}
}
public class YourClass
{
public IURLInvoke Invoker {get; set;}
public void InvokeURI(Uri myUri)
{
if(Invoker == null)
return;
string xml = Invoker.InvokeURI(Uri myUri);
// put your code for deserialization here
}
}
// here is an usage example:
YourClass a = new YourClass();
// set an Invoker, choose a strategy to invoke url
a.Invoker = new YourURLInvoker();
a.InvokeURI(url);
This approach is also called Strategy Pattern

Pls see dummy code using adapter pattern and dependency injection.
Idea is to create a interface and pass it around
public class Adapter{
public void processRequest(){
RequestProcessor processor = new RequestProcessor();
processor.processRequest();
}
}
public class RequestProcessor{
public void procesRequest(){
Irequest request = new HTTPRequest();
HTTPService service = new HTTPService();
// fetch the uri from builder class
URI url = URIBUIlder();
string response = service.sendRequest(request,url);
// now fetch type from just
Type t = Serializer.searialize<T>(response);
}
}
public Class Serializer{
public static T searialize<T>(string xml){
}
}
public interface IRequest{
public string sendRequest(uri url);
}
public class HTTPRequest:IRequest{
public string sendRequest(uri url){
// instantiate actual http request here and return response
}
}
//This will act as controller
public class HTTPService{
public string sendRequest(IRequest request,uri url) {
return request.sendRequest(url);
}
}

Related

accessing multi endpoints web services (ASMX) best practices in c#

I have a clean architecture project that provide micro services, one of which is to access Agresso ERP web services.
https://***************/service.svc
it provide many services
https://**/service.svc?FooService/Foo
https://**/service.svc?BooService/Boo
each of which has it's own service reference(connected service), and each of which has many methods.
each call to any of the end point you need to pass credentials with it.
var fooSoapClient = new FooSoapClient();
var credentials = new WSCredentials
{
Username = "fakeuser",
Password = "fakepassword",
Client = "fakeclient",
};
var result = fooSoapClient.GetFoosAsync(Foo filter,true,
credentials );
(P.S) credential class exist in all entities
namespace Foo1NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
namespace Foo2NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
i can access all end points with no problem.
I have the following Questions:
Is there a generic solution i can follow for not to Fall in DRY?
is there a design pattern that best target this issue?
Here is what I've done in the past, it fits in well into Dependency Injection/containers if you use that as well. The key thing here is to define an single interface that all services will implement. Your code that uses this should only be using the interface.
Each class should implement an interface you define, e.g. IWebServiceOperations
public interface IWebServiceOperations
{
WebServiceOperationResult GetFooAsync(WebServiceOperationRequest request);
}
I'll leave you to figure out the classes WebServiceOperationResult/Request, they just hold your request/response variables, including credentials.
Then each webservice you need to implement is done in a separate class. You also dictate in the constructor what type of implementation this is (FooSoap1 vs FooSoap2) e.g.
public class FooSoapClient : BaseClient, IWebServiceOperations
{
public FooSoapClient() : base(Clients.FooSoap1)
public GetFooAsync(...)
{
...
}
}
public class BaseClient
{
private readonly eFooServiceType _serviceType;
public eFooServiceType ServiceType {
get{
return _serviceType;
}
}
protected BaseClient(eFooServiceType service)
{
_serviceType = service;
}
}
Now you should have a bunch of class references. Either your DI container can resolve these for you, based on the service type you want, or you could add them to a Dictionary, so if you wanted to operate against FooSoap1, you'd do...
var fooSoapClient1 = myServices[Clients.FooSoap1];
await fooSoapClient1.GetFooAsync(...)

Autofac Wcf - Inject service depending on data within SOAP Request

I have a WCF Service with the following operation contract:
[OperationContract]
Response SearchEntities(Query query);
This operation takes a request that contains a specified Entity like so:
[DataContract]
public class Query
{
[DataMember]
public string SearchTerm { get; set; }
[DataMember]
public string Entity { get; set; }
[DataMember]
public bool ExactMatch { get; set; }
}
Based on the value contained within the Entity property, one the following properties is populated within this response:
[DataContract]
public class Response
{
[DataMember]
public List<Asset> Assets { get; set; }
[DataMember]
public List<Stage> Stages { get; set; }
[DataMember]
public List<Sector> Sectors { get; set; }
}
Terrible design, I know! However. I am using Autofac.Wcf as my service factory to inject dependencies. Normally I would use a common Interface and Generics to determine a service to use based on the Entity value like so:
public interface IEntitySearch<T>
{
Response Search(Query query);
}
The above interface would have several implementations for each of the Lists within the response. Using a design pattern such as a service location I could determine which service to use (all of which inherit from IEntitySearch<T>, something like:
public IEntitySearch ResolveSearcher(Query query)
{
switch(query.Entity)
{
case "Assets":
return _container.Resolve<AssetSearch>();
case "Stages":
return _container.Resolve<StageSearch>();
default:
throw new NotSupportedException();
}
}
While this works, a more elegant solution (I believe) would be to customize the Autofac container per request for this particular operation, depending on the data contained within the request.
IE: Before the WCF pipe line sends the request to the service implementation, is it possible to examine the request data and customize how the container resolves dependencies. That way I can avoid exposing dependency resolution within my service layer.
Is this possible?
If another DI library other than Autofac has a solution for this, I will happily change our DI framework.
Thanks.
I haven't personally tried this but I think a direction you can go down is to combine:
Using OperationContext.Current to get the current request message data.
Specifying a custom IServiceImplementationDataProvider for Autofac that tells Autofac which WCF interface to host for that request.
Using a lambda registration for your service implementation to switch the backing service based on OperationContext.Current.
You can see two examples of the IServiceImplementationDataProvider by looking at the DefaultServiceImplementationProvider - the one that works in Autofac WCF hosting by default; andMultitenantServiceImplementationDataProvider, which is more about generating a proxy to enable multitenant WCF hosting.
While neither of these use OperationContext.Current to determine the actual backing service, you can build on the ideas:
Look at the Autofac.Multitenant.Wcf implementation. You may be able to use it as-is. The point of the instance data provider there is that WCF grabs on to the concrete type of the service being hosted and if you try to swap types out from under it, you get errors. The multitenant support fools WCF by creating a proxy type and your implementation type can be swapped out under the proxy. Note the MultitenantServiceImplementationDataProvider doesn't actually tie anything to a tenant or tenant ID; it's only about that proxy.
In your .svc file specify a service interface rather than any individual concrete implementation since you'll be swapping out the implementation.
Use a lambda registration to figure out your implementation.
Make sure your service is InstanceContextMode.PerCall to ensure things get swapped out on a per request basis.
The registration might look something like this:
builder.Register(ctx => {
var context = OperationContext.Current;
var type = DetermineTypeFromContext(context);
return ctx.Resolve(type);
}).As<IMyServiceInterface>();
The Autofac WCF and Autofac Multitenant section on WCF may also help.
In my opinion you're trying to move your problem just to another place. Why would making decision based on request at low-level WCF is better than switch in SearchEntities method? It's much worse ;-)
I would consider to use IEntitySearch factory/provider e.q.IEntitySearchProvider (it's not so much better but always).
public interface IEntitySearch
{
bool IsMatchQuery(Query query);
Response Search(Query query);
}
// without service locator
public class EntitySearchProvider : IEntitySearchProvider
{
private readonly IEnumerable<IEntitySearch> _searchers;
public EntitySearchProvider(IEnumerable<IEntitySearch> searchers)
{
_searchers = searchers;
}
public IEntitySearch GetSearcher(Query query)
{
// last registered
return _searchers.LastOrDefault(i=>i.IsMatchQuery(query))
?? throw new NotSupportedException();
}
}
or
public interface IEntitySearchProvider
{
IEntitySearch GetSearcher(Query query);
}
public class EntitySearchProvider : IEntitySearchProvider
{
private readonly IComponentContext _container;
public EntitySearchProvider(IComponentContext container)
{
_container = container;
}
public IEntitySearch GetSearcher(Query query)
{
switch(query.Entity)
{
case "Assets":
return _container.Resolve<AssetSearch>();
case "Stages":
return _container.Resolve<StageSearch>();
default:
throw new NotSupportedException();
}
}
}
with
public class WcfService
{
private readonly IEntitySearchProvider _provider;
public WcfService(IEntitySearchProvider provider)
{
_provider = provider;
}
public Response SearchEntities(Query query)
{
var searcher = _provider.GetSearcher(query);
return searcher.Search(query);
}
}

Unit Test - How to MOQ WCF Client using MOQ

I've been looking at many other questions on SO, many similar, but none seem to match the style of service reference, hence me asking. Most of them talk about using ChannelFactory, but this one uses ClientBase. I'm learning more about Unit testing & Moq. I want to test our repository class, which makes a call to a WCF Service.
I've tried mocking this many ways, including creating a constructor on the repo, taking the FISP interface.
How can I work this to be usable in the repo and also unit testable, mocking the WCF operation using moq?
The repository didn't pass in the interface (yet), as below. It's using the proxy client class.
public class FisPRepository : IFisPRepository
{
private readonly FISPClient _fisPClient;
public FisPRepository()
{
_fisPClient = new FISPClient
{
ClientCredentials =
{
UserName = {UserName = "xyz", Password = "cba"}
}
};
public person GetPersonFromId(string id)
{
return _fisPClient.getPerson(new personRequest()
{
reference = new referenceFilter { type = "FWI", value = id },
});
}
}
Generated reference
And here's the generated Reference code -
Interface:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.aUrl.com/fwi", ConfigurationName="FISP.FISP")]
public interface FISP {
[System.ServiceModel.OperationContractAttribute(Action="http://www.aUrl.com/fwi/FISP/getPersonRequest", ReplyAction="http://www.aUrl.com/fwi/FISP/getPersonResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(FhSoap.FISP.FWiException), Action="http://www.aUrl.com/fwi/FISP/getPerson/Fault/FWiException", Name="FWiException")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(episodeTask))]
[return: System.ServiceModel.MessageParameterAttribute(Name="person")]
FhSoap.FISP.getPersonResponse getPerson(FhSoap.FISP.getPersonRequest request);
}
Client:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface FISPChannel : FhSoap.FISP.FISP, System.ServiceModel.IClientChannel {
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class FISPClient : System.ServiceModel.ClientBase<FhSoap.FISP.FISP>, FhSoap.FISP.FISP {
public FISPClient() {
}
public FISPClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
FhSoap.FISP.getPersonResponse FhSoap.FISP.FISP.getPerson(FhSoap.FISP.getPersonRequest request) {
return base.Channel.getPerson(request);
}
public FhSoap.FISP.person getPerson(FhSoap.FISP.personRequest request) {
FhSoap.FISP.getPersonRequest inValue = new FhSoap.FISP.getPersonRequest();
inValue.request = request;
FhSoap.FISP.getPersonResponse retVal = ((FhSoap.FISP.FISP)(this)).getPerson(inValue);
return retVal.person;
}
}
Update
Following the suggestions in the comments below I tried using the interface to construct the client, is that what's meant? As that doesn't then create a client, it creates a channel.
public FisPRepository()
{
var factory = new ChannelFactory<FISPChannel>("BasicHttpBinding_SomthingService");
var credentialBehaviour = factory.Endpoint.Behaviors.Find<ClientCredentials>();
credentialBehaviour.UserName.UserName = "xyz";
credentialBehaviour.UserName.Password = "cba";
_fisPClient = factory.CreateChannel();
}
That _fisPClient = factory.CreateChannel(); is invalid, as it it creates a FISPChannel, not client. What am I missing?
your repository is working with your concrete client, you need to inject the client into the class onto an interface
response:
#Kritner, The FISPChannel? As opposed to the FISP interface?
Well, the normal convention is for interfaces to be "I" something like IFISP, but either way, the IFISP interface is what I would have used in the past (instead of the IFISPChannel. Though currently, if you attempted to use FISP, that interface would not have access to the ClientCredentials that you're currently setting in the class when newing up the client.
Ideally, you would not be setting your credentials on each repository, but in some sort of configuration. Once you've done that, you can refactor to something like this:
public class FisPRepository : IFisPRepository
{
private readonly FISP _fisp;
public FisPRepository(FISP fisp)
{
_fisp = fisp;
}
public person GetPersonFromId(string id)
{
return _fisP.getPerson(new personRequest()
{
reference = new referenceFilter { type = "FWI", value = id },
});
}
}
and of course, when constructing your repository, you'll need to pass in a concretion of the client - but for unit testing you'll be able to mock the FISP.
You can get a concretion of the client in several ways.
Use an IOC container like Ninject, Unity, AutoFac, etc
New up the concretion directly
Use service location
As syntax differs depending on your IOC or service location, so here's how you could get a repository now directly:
FisPRepository myRepo = new FisPRepository(new FISPClient());
injecting your concretion and coding to an abstraction is a design pattern known as dependency injection.

Calling one ServiceStack 4 service from another with a file upload thrown in for fun

I have a working service in 4.0.31 that looks like this:
public object Post(MyDTO request)
{
foreach (var uploadedFile in base.Request.Files)
{
... do something ...
}
return new MyDTOResponse();
}
Everything works great, and I'm happy!
But now, I want to call the same service method from within another service, the way to do this apparently is:
public object Post(MyOtherDTO request)
{
var myService = base.ResolveService<MyService>();
// now I call some new method I wrote to bypass the file upload part, since
// myService.Post() doesn't know about the file upload part
var myResponse = myService.NewMethodThatLetsMePassAStreamToTheOtherService(streamData);
... do other stuff...
return new MyOtherDTOResponse();
}
While I'm not unhappy with this, it does create a hard dependency between the two services, so I'm not thrilled like I usually am with ServiceStack!
Is there a more elegant way of putting this together? I'm probably just missing something really, really obvious...
I'm not 100% clear on what the issue is, if it's how to share logic between services? then you could pull common logic out of each service class and reference the shared code in both Services.
If no dependencies are required I'll refactor the shared code behind re-usable extension methods.
If dependencies are required I will refactor it behind a shared logic class that's a dependency in both Services, see the IGreeter example in the sharing logic between MVC and ServiceStack answer:
public class MyService1 : Service
{
public ISharedDep SharedDep { get; set]
public object Any(Request1 request)
{
//...
}
}
public class MyService2 : Service
{
public ISharedDep SharedDep { get; set]
public object Any(Request2 request)
{
//...
}
}
Shared logic using Request Context using base class
If it's common code used by many Services that requires the base.Request context than you could move it to a common Service base class:
public class MyServiceBase : Service
{
public ISharedDep SharedDep { get; set]
public object SharedMethod(object request)
{
//...
}
}
public class MyServices1 : MyServiceBase { ... }
public class MyServices2 : MyServiceBase { ... }
Shared logic using Request Context using Extension method
If you prefer not to use a base class, this can be re-factored behind an extension method as well:
public static void MyServiceExtensions
{
public static object SharedMethod(this IServicBase service, object request)
{
var sharedDep = service.TryResolve<ISharedDep>();
return sharedDep.SharedMethodWithRequestCtx(request, service.Request);
}
}
Loose Coupling by executing a Request DTO
If the issue is about a loose-coupled way to call Services without a reference to the implementation itself you can execute the Request DTO with the ServiceController:
public class MyService : Service
{
public object Any(Request requestDto)
{
var altDto = new AltRequest { Id = requestDto.Id };
var response = HostContext.ServiceController.Execute(altDto, base.Request);
//...
}
}
Note: this API is available as base.ExecuteRequest(requestDto) in v4.0.32+.
Uploading Files to a HTTP Service In Memory
If the issue is instead how to execute a Service that handles file uploads, there's an example in the embedded version of HttpBenchmarks showing how to call a Service that processes HTTP File uploads with a custom Request Context that uses local FileSystem files instead:
using (var admin = Resolve<AdminServices>())
{
//...
var dir = new FileSystemVirtualPathProvider(this, Config.WebHostPhysicalPath);
var files = dir.GetAllMatchingFiles("*.txt")
.Concat(dir.GetAllMatchingFiles("*.zip"));
admin.Request = new BasicRequest
{
Files = files.Map(x => new HttpFile {
ContentLength = x.Length,
ContentType = MimeTypes.GetMimeType(x.Name),
FileName = x.Name,
InputStream = x.OpenRead(),
} as IHttpFile).ToArray()
};
if (admin.Request.Files.Length > 0)
{
admin.Post(new UploadTestResults
{
TestPlanId = 1,
TestRunId = testRun.Id,
CreateNewTestRuns = true,
});
}
}

Static helper using Session in MVC3 prevents me from unittesting

I'm writing a project in c# asp.net mvc3, and I have a helper-class that looks like this:
using System.Collections.Generic;
using System.Web;
namespace CoPrice.Helpers
{
public static class Messages
{
public static IList<Message> All
{
get
{
var list = ((IList<Message>)HttpContext.Current.Session["_messages"]) ?? new List<Message>();
HttpContext.Current.Session["_messages"] = new List<Message>();
return list;
}
}
public static bool Exists
{
get
{
return (((IList<Message>)HttpContext.Current.Session["_messages"]) ?? new List<Message>()).Count > 0;
}
}
public static void Add(MessageType type, string message)
{
Message m = new Message
{
Type = type,
Text = message
};
HttpContext.Current.Session["_messages"] = HttpContext.Current.Session["_messages"] as List<Message> ?? new List<Message>();
((IList<Message>)HttpContext.Current.Session["_messages"]).Add(m);
}
public enum MessageType
{
Info,
Success,
Error
}
public struct Message
{
public MessageType Type;
public string Text;
}
}
}
However, when I try to use these in a test, it crashes (cause of HttpContext.Current beeing null). How can I make this work both in tests and in the app itself? I don't mind having to change this class to use something else than HttpContext.Current to access the session, but I want it to have properties as it does, so it can't take the session-object as a parameter.
Any ideas on how to solve this problem?
You need to define an IMessagesProvider and use an DI container to inject the implementation of the IMessagesProvider. In real use you'll have an implementation that uses the ASP.Net session. In test use you'll mostly mock it. BTW, you probably shouldn't have a static Messages class. In fact, IMessagesProvider will probably replace your static Messages class.
Ex:
public class FooController : Controller
{
IMessagesProvider _messages;
public FooController(IMessagesProvider messages)
{
// Your DI container will inject the messages provider automatically.
_messages = messages;
}
public ActionResult Index()
{
ViewData["messages"] = _messages.GetMessages(Session.SessionId);
return View();
}
}
Mind you, this is a very simple example. In fact, you probably want one more class which is the model that drives the view. A quick intro:
public ActionResult Index()
{
var model = PrepareModel(_messages);
return View(model);
}
"PrepareModel" is your very own method that instantiates a new model class, fills it with the necessary data, and then you send it off to your view. It's typical to have one model class per view defined. E.g. you'd have model classes like "SignupFormModel", "DashboardModel", "ChatModel", etc., Doing so allows you to have strongly-typed views as well (a great thing).
You can also implement a mock session object that inherits from HttpSessionStateBase class
#xanadont is right that you need to turn Messages into a normal class. But (and I know this is heresy in some circles) there's no need for a one-off interface and a full-blown DI framework. Just make the methods on your Messages class virtual so you can mock them in your unit-tests, and use constructor injection:
public class FooController : Controller
{
Messages _messages;
// MVC will call this ctor
public FooController() : this(new Messages())
{
}
// call this ctor in your unit-tests with a mock object, testing subclass, etc.
public FooController(Messages messages)
{
_messages = messages;
}
}

Categories

Resources