Currently I'm writing a bot for a browsergame and there are several responses.
They are unencrypted and the data is provided by a normal http response.
So because there are severaly slightly different response-types and structures I thought I could use my (low) oop knowledge to handle this - but my concept does not work.
I thought I can make for each request (login request, logout request, attack request, harvest request, ..) a own class which is a child from the basic request class.
And the same concept I thought I can do for the responses.
So here is a small demo of my code:
public class BasicRequest
{
public BasicRequest(string serverId) { }
public virtual BasicResponse DoRequest(string[] requestData)
{
// request is handled here
}
}
public class LoginRequest : BasicRequest
{
public LoginRequest(string serverId) : base(serverId) { }
}
public class BasicResponse
{
public BasicResponse(string[] responseData) { }
public virtual void DoSomeStuffWithTheResponse() { }
}
public class LoginResponse : BasicResponse
{
public LoginResponse(string[] responseData) : base(responseData) { }
public override void DoSomeStuffWithTheResponse() { }
}
This is my basic structure (ofc I have some more request and response classes).
Now I tried to use it like this:
LoginResponse response = new LoginRequest("serverXX").DoRequest(new string[] { "data" }) as LoginResponse;
But then 'response' is just null.
The important thing is, that it should perform the actions that the constructor of the base class do (this is some basic stuff that every request and response need) and then the constructor and the override of the specific class (loginrequest/response in this case) should be called.
Hope you can help me out, thanks in advice.
Since you haven't overriden DoRequest in your LoginRequest class, when you invoke DoRequest the base classes implementation is being called.
In order for this to work, LoginRequest needs to override the base implementation:
public class LoginResponse : BasicResponse
{
public LoginResponse(string[] responseData) : base(responseData) { }
public override void DoSomeStuffWithTheResponse()
{
}
public override BasicResponse DoRequest(string[] requestData)
{
// Do stuff
return new LoginResponse();
}
}
Related
I have a list of Proxy Servers. Using these Proxy Servers, I want to hit URL to get data programmatically. I want to apply retry pattern here. For example, If I cannot get data from Proxy Server 1, I would like to hit URL using Proxy Server 2 and so on. What should I write in ProxyHelper class GetData method as per good design practices.
Sample Code :
Interface IProxyServer {
IResponse GetData(String URL);
}
public class ProxyServerA implements IProxyServer {
public IResponse GetData(String URL)
{
//some code
}
}
public class ProxyServerB implements IProxyServer {
public IResponse GetData(String URL) {
//some code
}
}
public class ProxyHelper {
public List<IProxyServer> _proxyservers = new List<IProxyServer>();
public IResponse GetData(String URL)
{
// Following the best practices, what should be the code here which will implement retry mechanism
// and call other available proxy server in case the request is failed.
}
public void Add(IProxyServer proxyserver)
{
_proxyservers.Add(proxyserver);
}
}
void main() {
ProxyHelper proxyHelper = new ProxyHelper();
String URL = "www.google.com";
proxyserver.Add(new ProxyServerA());
proxyserver.Add(new ProxyServerB());
var response = ProxyHelper.GetData(URL);
}
I have an ASP.NET MVC 5 Application with a SignalR 2 hub and using autofac for the DI.
The entire business logic is encapsulated in manager classes in their own layer. Some manager methods need informations about the current logged in user (UserId, TenantId, ..).
I solved this problem by injecting an AuthorizationProvider into each manager class that needs the user information.
public interface IAuthorizationProvider
{
long? GetUserId();
long? GteTenantId();
}
public class MyManager : IMyManager
{
private IAuthorizationProvider _authorizationProvider;
public MyManager(IAuthorizationProvider authorizationProvider)
{
_authorizationProvider = authorizationProvider;
}
public void MyMethod()
{
// Getting the User information here is pretty simple
long userId = _authorizationProvider.GetUserId();
}
}
Normally I can get the user information from the HttpContext and from the session. So I wrote a SessionAuthorizationProvider:
public class SessionAuthorizationProvider{
public long? GetUserId()
{
HttpContext.Current?.Session?[SessionKeys.User]?.Id;
}
public long? GteTenantId() { ... }
}
But now I have a new method in the SignalR hub that use the same mechanism.
[HubName("myHub")]
public class MyHub : Hub
{
private IMyManager _myManager;
public MyHub(IMyManager myManager)
{
_myManager = myManager;
}
[HubMethodName("myHubMethod")]
public void MyHubMethod(long userId, long tenantId)
{
_myManager.MyMethod();
}
}
The problem is that a SignalR request doesn't have a session. Therefore I have also set the required user information in the hub method as parameters postet from the client.
So I thought it is the best solution for this problem to write a new AuthorizationProvider for SignalR and adapt the depdendency resolver. But I can't get the current user in the new SignalrAuthorizationProvider.
public class SignalrAuthorizationProvider{
public long? GetUserId()
{
// How to get the user information here???
}
public long? GteTenantId() { /* and here??? */ }
}
Is there a recommended solution to this problem?
Of course, I can extend MyMethod to accept the user information as a parameter. But MyMethod calls another method from another manager and that manager also calls another method. The user information is only needed for the last method call. So I had to change at least 3 methods and many more in the future.
Here is a sketch of the problem
This is a potential solution. But it's very bad
Session is not supported by SignalR by default and you should avoid using it. See No access to the Session information through SignalR Hub. Is my design is wrong?. But you still can use cookie or querystring to get the desired value.
In both case you need to have access to the HubCallerContext of the underlying hub, the one that is accessible through the Context property of the Hub.
In a ideal word you should just have to had the dependency to the SignalAuthorizationProvider
ie :
public class SignalrAuthorizationProvider {
public SignalrAuthorizationProvider(HubCallerContext context){
this._context = context;
}
private readonly HubCallerContext _context;
public long? GetUserId() {
return this._context.Request.QueryString["UserId"]
}
}
But due to SignalR design it is not possible. Context property is assigned after construction of the Hub and AFAIK there is no way to change it.
Source code here : HubDispatcher.cs
One possible solution would be to inject a mutable dependency inside the Hub and alter the object in the OnConnected, OnReconnected methods.
public class SignalrAuthorizationProvider : IAuthorizationProvider
{
private Boolean _isInitialized;
private String _userId;
public String UserId
{
get
{
if (!_isInitialized)
{
throw new Exception("SignalR hack not initialized");
}
return this._userId;
}
}
public void OnConnected(HubCallerContext context)
{
this.Initialize(context);
}
public void OnReconnected(HubCallerContext context)
{
this.Initialize(context);
}
private void Initialize(HubCallerContext context) {
this._userId = context.QueryString["UserId"];
this._isInitialized = true;
}
}
and the Hub
public abstract class CustomHub : Hub
{
public CustomHub(IAuthorizationProvider authorizationProvider)
{
this._authorizationProvider = authorizationProvider;
}
private readonly IAuthorizationProvider _authorizationProvider;
public override Task OnConnected()
{
this._authorizationProvider.OnConnected(this.Context);
return base.OnConnected();
}
public override Task OnReconnected()
{
this._authorizationProvider.OnReconnected(this.Context);
return base.OnReconnected();
}
}
Having a mutable dependency is not the best design but I can't see any other way to have access to IRequest or HubCallerContext.
Instead of having an abstract Hub class which is not a perfect solution. You can change the RegisterHubs autofac method to use AOP with Castle.Core and let the interceptor calls the methods for you.
I need to access request context, specifically the Items inside my custom class and I don't want to do have it either inheriting from ServiceStack Service or having the set it up inside the my Service.
So if I have a class like below which the implementer class (ContextItemsGetter) also implements IRequiresRequest, I would expect the Request property to be populated.
public interface IGetContextItems
{
string Get(string key);
}
public class ContextItemsGetter : IGetContextItems, IRequiresRequest
{
public string Get(string key)
{
//someway to access http context items
//im RequestContext.Instance.Items[key] e.g. Prop1 Prop2
//or Request.blah but Request is always null
}
public IRequest Request { get; set; }
}
https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IRequiresRequest.cs
However the Request is always null for both when SessionIdGetter is called from a genuine HTTP request or a redis message request. Am I doing something wrong? The purpose is to decouple and use Items to pass information between http request and redis message request.
I've also tried to use RequestContext.Instance.Items, where this worked for HTTP request, but during redis message request, the items are not there, the keys where I populated just before calling ExecuteMessage are not there.
var req = new BasicRequest { Verb = HttpMethods.Get };
req.Items.Add("Prop1", m.GetBody().Prop1);
req.Items.Add("Prop2", m.GetBody().Prop2);
var result = HostContext.ServiceController.ExecuteMessage(m, req);
I'm using version 4.0.50.
Also, this page Access HTTP specific features in services where mentions
Note: ServiceStack's Service base class already implements IRequiresRequestContext which allows you to access the IRequestContext with base.RequestContext and the HTTP Request and Response with base.Request and base.Response.
I believe IRequiresRequestContext is now called IRequiresRequest, so I think the doc should be updated.
Updated: full code to demo my original intention:
[Route("/test", Verbs = "GET")]
public class Dto : IReturnVoid
{ }
public class DtoService : Service
{
//So that IGetContextItems is taken care of by IDependencyThatUsesIGetContextItems
public IDependencyThatUsesIGetContextItems DependencyThatUsesIGetContextItems { get; set; }
public void Get(Dto req)
{
DependencyThatUsesIGetContextItems.SomeMethod();
}
}
public interface IGetContextItems
{
string Get(string key);
}
//since ContextItemsGetter implmeents IRequiresRequest
//I can still easily test any service that uses IGetContextItems by mocking IGetContextItems
public class ContextItemsGetter : IGetContextItems, IRequiresRequest
{
public IRequest Request { get; set; }
public string Get(string key)
{
//either through injection
//return Request.Items[key].ToString();
//or some static class
//return RequestContext.RequestItems.Items[key].ToString();
return RequestContext.Instance.Items[key].ToString();
}
}
public interface IDependencyThatUsesIGetContextItems
{
string SomeMethod();
}
public class DependencyThatUsesIGetContextItems : IDependencyThatUsesIGetContextItems
{
//this will be inejcted
public IGetContextItems ContextItemsGetter { get; set; }
public string SomeMethod()
{
var a = ContextItemsGetter.Get("SomeKey");
return "blah";
}
}
IRequiresRequest only injects the current IRequest to your Service classes and Validation Filters, it doesn't inject the IRequest into your dependencies which are resolved directly from the IOC and who doesn't have access to current IRequest to be able to inject.
Also ServiceStack's convenient Service and AbstractValidator<T> base classes already implement IRequiresRequest so in most cases the places where IRequiresRequest applies has already been implemented so you shouldn't need to implement it yourself.
The recommended approach to passing the IRequest into your dependencies is to pass them as a parameter from your Service, e.g:
public class MyServices : Service
{
public IGetContextItems ContextItems { get; set; }
public object Get(Request request)
{
return ContextItems.Get(base.Request, request.Id);
}
}
You do have an opportunity to inspect and modify your Service instance before it executes your Service by overriding OnPreExecuteServiceFilter() in your AppHost to go through and inject the IRequest in each of your Services dependencies that implement IRequiresRequest with:
public override object OnPreExecuteServiceFilter(IService service,
object request, IRequest req, IResponse res)
{
service.InjectRequestIntoDependencies(req);
return request;
}
Which calls the below extension method will recursively populate your Services dependency graph as long as each parent implements IRequiresRequest:
public static class ServiceExtensions
{
public static void InjectRequestIntoDependencies(this object instance, IRequest req)
{
foreach (var pi in instance.GetType().GetPublicProperties())
{
var mi = pi.GetGetMethod();
if (mi == null)
continue;
var dep = mi.Invoke(instance, new object[0]);
var requiresRequest = dep as IRequiresRequest;
if (requiresRequest != null)
{
requiresRequest.Request = req;
requiresRequest.InjectRequestIntoDependencies(req);
}
}
}
}
But you need to be careful to not implement IRequiresRequest on any of your Singleton dependencies (the default scope) as it's not ThreadSafe whereas passing IRequest as a parameter would be.
Also to avoid coupling your logic classes to ServiceStack I'd consider only passing in what your dependencies needs from IRequest instead of the IRequest instance itself which will also make it easier to test.
We have an application that contacts several diffrent remote services(SOAP, HTTPREQUEST). We then do different actions(import, export, update, delete).
Today we have two client classes and four action classes.
QUESTION!
How can I decouple these two modules so that I have to do the least changes. IE only add a new action/new client. Nothing more.
Client class
Authorizes our client against the remote service, it handles logging in and out.
Action class
Holds the url, method to invoke against the client. Aswell as the ExecuteActionMethod
Usage
Client class get's decorated with an action and then performs the action with the client.
Fears
I dont want to: - create a new action class everytime I add a new client class - create a new client class everytime I add a new action class - No god object factory that needs to know everything
Problem
The problem with this approach is that when talking to different clients, I need diffrent information in this case different URLS, talking to the Soap service needs invoking of the correct method. The action itself is the keeper of this information. But as I dig deeper this certainly is something that will change.
Scenario 1#
I end up creating classes that combine both action and result. So I have classes like "HttpImport"(based on HttpClient and ImportAction). Which results in X(Clients) * Y(Actions) which now would total at 8 classes, which is really bad.
Scenario 2#
Time for some code! In this scenario the implementation binds my classes together even though I use abstractions.
Problem here is that every action need to have a property for each of the clients(remember they visit different endpoints). So if i were to add one more client I would have to go through all the actions and add another property for that clients endpoint, aswell as add another deocrator to delegete all calls to the correct endpoint(remember i have three properties now in every action). If I were to create another action, it would just be that action. So N*times actions + 1(the action), in this case 5 changes. A little bit better but still not there.
Scenario 3#
This is the God object factory. Here we get rid of the properties holding the endpoints, and we supply the enpoint via the constructor. This will result in methods for creating all sorts of clients and actions. Same as above X(Clients) * Y(Actions) if something were to be added, these accumulate into 8 new methods inside the factory. The factory must also hold endpoint information.
Code
My code has evolved to the 2:nd scenario. I dont want to build the factory, and I'm looking to you guys.
Something tells me that the client classes does to much and should somehow be decoupled, from the classes they instansiate inside.
Main
static void Main(string[] args)
{
IAction iact = new ImportAction();
IDecorator idec = new HttpDecorator(iact);
IClient icli = new HttpClient(idec);
Console.Write(icli.connect().ToString());
Console.ReadKey();
}
IAction
public interface IAction
{
string[] Execute();
string HttpString { get; }
string SoapMethod { get; }
}
ImportAction
class ImportAction : IAction
{
private string soapmethod;
private string httpUrl;
public ImportAction()
{
this.HttpString = #"http://www.hereiswereactionsgo.com";
}
public string[] Execute()
{ //Execute the action!
return null;
}
public string HttpString { get; set; }
public string SoapMethod { get; set; }
}
IDecorator
public interface IDecorator
{
string GetActionString();
}
HttpDecorator
class HttpDecorator : IDecorator
{
private IAction _action;
public HttpDecorator(IAction action)
{
this._action = action;
}
public string GetActionString()
{
return _action.HttpString;
}
public string[] Execute()
{
throw new NotImplementedException();
}
}
IClient
public interface IClient
{
bool connect();
}
HttpClient
class HttpClient : IClient
{
private string _username;
private string _password;
private IDecorator _myaction;
private HttpWebRequest webReq;
public HttpClient(IDecorator action)
{
this._username = "myusername";
this._password = "mypassword";
this._myaction = action;
}
public bool connect()
{
bool result = false;
webReq = (HttpWebRequest)WebRequest.Create(_myaction.GetActionString());
webReq.Credentials = new NetworkCredential(_username, _password);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)webReq.GetResponse();
if (myHttpWebResponse.StatusCode == HttpStatusCode.OK)
{
result = true;
}
return result;
}
}
Visitor pattern seems suitable for this (Visitor) .
Treat Actions as the Visitors and Clients as Elements to visit. Keeping Action as an abstract class rather than interface may help by providing the boilerplate code.
To add a new Action extend BaseAction. Implement methods such as getHttpUrl(), getHttpBody() etc.
To add a new Client will require changes to existing classes. You have to implement corresponding methods in each Action class. I assume adding a new Client will happen less frequently.
The sample code below follows Java syntax.
public static void main() {
new HttpClient().performAction(new ImportAction());
}
public interface Client {
performAction(Action);
}
public class HttpClient implements Client {
public void accept(IAction a) {
a.visitHttp(this);
}
}
public abstract class Action {
public visitHttp(HttpClient c) {
getHttpUrl();
c.connect(getHttpUrl());
c.send(getHttpBody());
c.close;
}
public visitSoap(SoapClient c) {
}
public abstract String getHttpUrl();
public abstract String getHttpBody();
}
ImportAction extends Action {
#Override
getHttpUrl() {
}
#Override
getHttpBody() {
}
}
I am just starting to familiarise myself with ServiceStack and have come upon FluentValidation. I have followed the introductions and created a small Hello App.
My problem is that when I try to validate the request DTO no error messages are returned to describe how it failed validation, only a blank Json object {}.
Myself, I think the validation is autowired to the DTO so there should be no need for me to write any extra code.
The answer is probably blatant but I cannot see it. Any help would be greatly appreciated. My code is below:
namespace SampleHello2
{
[Route("/hello")]
[Route("/hello/{Name}")]
public class Hello
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
public class HelloService : Service
{
public object Any(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
public class HelloValidator : AbstractValidator<Hello>
{
public HelloValidator()
{
//Validation rules for all requests
RuleFor(r => r.Name).NotNull().NotEmpty().Equal("Ian").WithErrorCode("ShouldNotBeEmpty");
RuleFor(r => r.Name.Length).GreaterThan(2);
}
}
public class Global : System.Web.HttpApplication
{
public class HelloAppHost : AppHostBase
{
//Tell Service Stack the name of your application and where to find your web services
public HelloAppHost() : base("Hello Web Services", typeof(HelloService).Assembly) { }
public override void Configure(Funq.Container container)
{
//Enable the validation feature
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(HelloValidator).Assembly);
//register any dependencies your services use, e.g:
// container.Register<ICacheClient>(new MemoryCacheClient());
}
}
//Initialize your application singleton
protected void Application_Start(object sender, EventArgs e)
{
new HelloAppHost().Init();
}
}
}
P.S. Really enjoying using ServiceStack, It really is a fantastic project so thanks.
Edit
So for example:
Calling: http://localhost:60063/hello/Ian?format=json returns {"Result":"Hello, Ian"}.
Whereas Calling: http://localhost:60063/hello/I?format=json returns {}.
The second call returns {} where I was expecting auto generated error messages.
I found the answer. It was an overlook on my behalf:
This was in the documentation and I overlooked it:
All Error handling and validation options described below are treated
in the same way - serialized into the ResponseStatus property of your
Response DTO making it possible for your clients applications to
generically treat all Web Service Errors in the same way.
So all that was missing from my code was to add the following line into the HelloResponse class.
public ResponseStatus ResponseStatus { get; set; }