Apply an attribute to a WCF service method to access Cookies - c#

Is there a way to apply a custom attribute to a WCF service method that can access the Cookies header? The WCF service is REST based and will only ever be consumed over HTTP transports.
So far the only way I have found to get an attribute to apply to my WCF service methods is by implementing the IOperationBehavior interface. With that I can at least get my attribute instantiated and the IOperationBehavior methods get called but how do I get from there to somewhere I can access HttpContext.Current to get at the Cookies?
My attribute is:
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute, IOperationBehavior
{
public MyAttribute()
{
int x = 1;
}
void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(this);
}
void IOperationBehavior.Validate(OperationDescription operationDescription)
{
var context = HttpContext.Current;
int y = 2;
}
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
var context = HttpContext.Current;
int y = 2;
}
public object BeforeCall(string operationName, object[] inputs)
{
return null;
}
}
I'm applying it on my service method using:
public class MyService : IMyService
{
[MyAttribute]
public bool IsAlive()
{
return true;
}
}

You can use HttpContext.Current.Request.Cookies[] in your service method to access cookies. You don't need to write custom attribute to achieve it

Related

Custom Attribute settings in .net Core

I am writing a very simple custom attribute to be used with my methods for ASP.net Core. The attribute is to handle feature flags which indicate an endpoint method is "switched on or off" as follows:
1) If a feature is turned ON, allow the code to pass through to the method and execute it as normal.
2) If the feature is turned OFF, just return from the attribute and dont execute the method within
I was thinking something along the lines of this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FeatureFlagAttribute : ActionFilterAttribute
{
private Dictionary<string, bool> myFeaturesList;
private readonly string selectedFeature;
public FeatureFlagAttribute(string featureName)
{
selectedFeature = featureName;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var found = myFeaturesList.TryGetValue(selectedFeature, out var result);
if (!found || !result)
{
// dont continue
context.HttpContext.Response.StatusCode = 403;
}
}
}
I need the myFeaturesList populated for this to work BUT I dont want to pass it into the constructor every time this is being used. Whats the best way to configure this? I was thinking of setting a static property in the attribute but thought this was a bit of a lame approach and that there must be a better way. Thanks in advance!
Alternatively, you could extract the creation of featureNames into an injectable service (registered to DI) and use your attribute as a type filter or with IFilterFactory.
Using type filters, you would create your attribute as:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FeatureFlagAttribute : ActionFilterAttribute
{
private readonly string _featureName;
private readonly IFeatureService _featureService;
public FeatureFlagAttribute(string featureName, IFeatureService featureService)
{
_featureName = featureName;
_featureService = featureService;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var features = _featureService.GetMyFeatures();
var found = features.TryGetValue(_featureName, out var result);
if (!found || !result)
{
// don't continue
context.HttpContext.Response.StatusCode = 403;
}
}
}
In the constructor parameters, featureName stays the same, and needs to be defined to the attribute, while featureService will get resolved from the DI, so you need to register an implementation for this in your startup's ConfigureServices().
The attribute usage changes a bit with type filters, for example:
[TypeFilter(typeof(FeatureFlagAttribute), Arguments = new object[] { "feature-A" })]
public IActionResult Index()
{
return View();
}
You can read more options of injecting dependencies into filters in the docs:
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2#dependency-injection
A different approach, but maybe move that out of the attribute, perhaps using a static event as the API hook? then you can put the dictionary where-ever you want?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FeatureFlagAttribute : ActionFilterAttribute
{
public FeatureFlagAttribute(string featureName)
{
selectedFeature = featureName;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (IsActive?.Invoke(selectedFeature) == false)
{
// dont continue
context.HttpContext.Response.StatusCode = 403;
}
}
public static event Func<string, bool> IsActive;
}
(note that you need to be careful with static events not to cause memory leaks)
Alternatively, keep what you have, but make the dictionary static (and thread-protected, etc); then add some kind of API like:
public static void SetFeatureEnabled(string featureName, bool enabled);
that tweaks the static dictionary.

how to add delegate class for service manager class when calling soap service in c#?

First of all, I want to share my scenario what i want to build -
Scenario:
I am building a client app using wpf. In some cases, I need to call a web service to get data from the server. In order to do this, I added a web reference using wsld url. And I created a ServiceManager class that will call service method. For security reason, I need to add some header info at soap xml request for example, UserToken, SAML Token and so on. I can this from my ServiceManager class. But I want to add another class which will be called before sending request to the server. In that class, I will do something like adding security header to soap xml request with request and then send it to the server.
I used SOAP Extension to fulfill my purpose and it works well. But the problem is, every-time I need to add annotation in Reference.cs (for each web service reference) file at top of the service method. I believe that there is some other easiest way to make this working better than SOAP Extension. Is there any way where I can only call the service and a delegate class will be called automatically and I don't need to add any annotation to the reference file? I will share my sample code here.
ServiceManage class:
public class ServiceManager
{
public UserDataService dataService; //web service added at Web Reference
public ServiceManager()
{
dataService = new UserDataService();
getUserServiceRequest rqst = new getUserServiceRequest();
getUserServiceResponse resp = dataService.getUser(rqst);
}
}
Reference.cs
[TraceExtensionAttribute(Name = "First")]
public getUserServiceResponse getUser([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] getUserServiceRequest request) {
object[] results = this.Invoke("getUser", new object[] {
request});
return ((getUserServiceResponse)(results[0]));
}
TraceExtensionAttribute.cs
[AttributeUsage(AttributeTargets.Method)]
public class TraceExtensionAttribute : SoapExtensionAttribute
{
private string mstrName = null;
public override Type ExtensionType
{
get { return typeof(TraceExtension); }
}
public override int Priority
{
get { return 1; }
set { }
}
public string Name
{
get { return mstrName; }
set { mstrName = value; }
}
}
TraceExtension.cs
public class TraceExtension : SoapExtension
{
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attr){//..do something}
public override void Initialize(object initializer){//..do something}
public override Stream ChainStream(Stream stream){//...do something}
public override void ProcessMessage(SoapMessage message) {//..do something}
}
Finally, I found the solution. Just through out Web Reference and add Service Reference instead. Then go to the following link. It works for me.

How to use IRequiresRequest to inject IRequest in ServiceStack?

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.

Validate WCF user based on URL

If I have a wcf rest service such as http://somedomain.com/service.svc/uniqueid/somemethod/parameter1
then is there a way to globally check if the uniqueid is valid for every request hitting the server.
I could put in a check for every operation contract but I'm looking for a way where this is not needed so that everytime the service is accessed the uniqueid is checked and does not proceed if invalid.
Just for some further background as to what I'm trying to achieve... The WCF service is an open API. Getting a uniqueid is also open and requires no kind of signup. I want to use the uniqueid so if the API is abused I can easily pull 1 ID's access without affecting any of the other users of the system.
UPDATE:Based on Mike's Suggestion I've created an IParameterInspector
[AttributeUsage(AttributeTargets.Class)]
class IDParameterInspector : Attribute, IParameterInspector
And attached it to my Service class
[IDParameterInspector]
public class MetaData : IMetaData
The problem I now have is the ApplyDispatchBehavior never runs.
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
{
if (channelDispatcher == null)
{
continue;
}
foreach (var endPoint in channelDispatcher.Endpoints)
{
if (endPoint == null)
{
continue;
}
foreach (var operation in endPoint.DispatchRuntime.Operations)
{
operation.ParameterInspectors.Add(this);
}
}
}
}
Does anyone now what I'm doing wrong?
This is how to use a parameter inspector and custom behaviour via attributes. You need to unfortunately implement both.
So starting with the decoration of the service method in the interface
[MyFirstCustomBehavior()]
string SayHello(string language);
We then need to define the MyFirstCustomBehavior class.
internal sealed class MyFirstCustomBehavior : Attribute, System.ServiceModel.Description.IOperationBehavior
{
#region IOperationBehavior Members
public void AddBindingParameters(System.ServiceModel.Description.OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
//no special behaviour
}
public void ApplyClientBehavior(System.ServiceModel.Description.OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
{
throw new NotImplementedException();
}
public void ApplyDispatchBehavior(System.ServiceModel.Description.OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(new MyFirstCustomParameterInspector());
}
public void Validate(System.ServiceModel.Description.OperationDescription operationDescription)
{
//no special behaviour
}
#endregion
}
We then need to code up the inspector.
internal sealed class MyFirstCustomParameterInspector : System.ServiceModel.Dispatcher.IParameterInspector
{
#region IParameterInspector Members
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
////do stuff here
}
public object BeforeCall(string operationName, object[] inputs)
{
////or here
return null;
}
#endregion
}
You should then be good to go.
You can try creating a custom service behavior that will affect all the incoming requests.
Here is an example that filters the requests based upon IP address and you can use that as a reference. If I get some time I'll post some code.

What's the best ASP.NET file type for a (non-SOAP, non-WSDL) web services project?

Haven't done ASP.NET development since VS 2003, so I'd like to save some time and learn from other's mistakes.
Writing a web services app, but not a WSDL/SOAP/etc. -- more like REST + XML.
Which of the many "New Item" options (Web Form, Generic Handler, ASP.NET Handler, etc.) makes the most sense if I want to handle different HTTP verbs, through the same URI, separately. In a perfect world, I'd like the dispatching done declaratively in the code rather than via web.config -- but if I'm making life too hard that way, I'm open to change.
If you're not using the built in web services (.asmx), then you should probably use a generic handler (.ashx).
This is an idea I've been playing with... use at your own risk, the code is in my "Sandbox" folder ;)
I think I want to move away from using reflection to determine which method to run, it might be faster to register a delegate in a dictionary using the HttpVerb as a key. Anyway, this code is provided with no warranty, blah, blah, blah...
Verbs to use with REST Service
public enum HttpVerb
{
GET, POST, PUT, DELETE
}
Attribute to mark methods on your service
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)]
public class RestMethodAttribute: Attribute
{
private HttpVerb _verb;
public RestMethodAttribute(HttpVerb verb)
{
_verb = verb;
}
public HttpVerb Verb
{
get { return _verb; }
}
}
Base class for a Rest Service
public class RestService: IHttpHandler
{
private readonly bool _isReusable = true;
protected HttpContext _context;
private IDictionary<HttpVerb, MethodInfo> _methods;
public void ProcessRequest(HttpContext context)
{
_context = context;
HttpVerb verb = (HttpVerb)Enum.Parse(typeof (HttpVerb), context.Request.HttpMethod);
MethodInfo method = Methods[verb];
method.Invoke(this, null);
}
private IDictionary<HttpVerb, MethodInfo> Methods
{
get
{
if(_methods == null)
{
_methods = new Dictionary<HttpVerb, MethodInfo>();
BuildMethodsMap();
}
return _methods;
}
}
private void BuildMethodsMap()
{
Type serviceType = this.GetType();
MethodInfo[] methods = serviceType.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach (MethodInfo info in methods)
{
RestMethodAttribute[] attribs =
info.GetCustomAttributes(typeof(RestMethodAttribute), false) as RestMethodAttribute[];
if(attribs == null || attribs.Length == 0)
continue;
HttpVerb verb = attribs[0].Verb;
Methods.Add(verb, info);
}
}
public bool IsReusable
{
get { return _isReusable; }
}
}
Sample REST Service
public class MyRestService: RestService
{
[RestMethod(HttpVerb.GET)]
public void HelloWorld()
{
_context.Current.Response.Write("Hello World");
_context.Current.Response.End();
}
}
Probably MVC if you need rest.
I agree with the ashx, gives you the most control. you could also go more complex and create a custom Http Handler. that way you can intercept any extension you decide. Of course you could add an Http Module and rewrite any request to a generic ashx handler.

Categories