I'd like to enforce authentication on some auto querys.
[Authenticate]
public class BusinessEntitiesService : QueryDb<DataModel.dbo.BusinessEntity>
{
}
Here's my issue. The above class is in my ServiceModel project... in order to add the [Authenticate] attribute, I need to add a reference to ServiceStack.dll which I think can cause issues down the road (according to previous guidance to only reference ServiceStack.Interfaces in the ServiceModel). I can't add the above class to ServiceInterfaces because then I'd have to reference that everywhere I use the client.
I've also tried using a GlobalRequestFilter... but that appears to goof with the AdminFeature plugin:
private bool IsAProtectedPath(string path)
{
return !path.StartsWith("/auth") && !path.StartsWith("/autoquery");
}
GlobalRequestFilters.Add((httpReq, httpResp, requestDto) =>
{
if(IsAProtectedPath(httpReq.PathInfo))
new AuthenticateAttribute().Execute(httpReq, httpResp, requestDto);
});
Not really sure how to best handle this.
In order to apply the [Authenticate] attribute to AutoQuery Services you would need to create a custom AutoQuery implementation and apply your Filter attributes on that, e.g:
[Authenticate]
public class MyProtectedAutoQueryServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
public object Any(QueryBusinessEntity query) =>
AutoQuery.Execute(query, AutoQuery.CreateQuery(query, Request));
public object Any(QueryBusinessEntity2 query) =>
AutoQuery.Execute(query, AutoQuery.CreateQuery(query, Request));
}
An alternative is to dynamically add attributes to your AutoQuery Request DTO, but these would need to be registered before Configure() is called, either before appHost.Init() or in your AppHost constructor, e.g:
public class AppHost : AppHostBase
{
public AppHost()
{
typeof(QueryBusinessEntity)
.AddAttributes(new AuthenticateAttribute());
}
}
Related
I want to return a custom class from my custom AutoQuery endpoint that inherits QueryResponse<T> but adds a few extra properties.
public class WritingAssignmentBlogLookUpResponse : QueryResponse<BlogDto>, IResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string DebugMessage { get; set; }
}
But if I specify request like so:
[Route("/assignment/blogs/", "POST")]
public class WritingAssignmentBlogsLookUpRequest : QueryDb<Blog, BlogDto>, IReturn<WritingAssignmentBlogLookUpResponse>
{
}
Then the return type specified in generatd DTO for client.post(req) is QueryResponse<BlogDto> and it doesn't generate WritingAssignmentBlogLookUpResponse at all.
Do I just have to specify return type as any from my typescript service or is there a way to make the types match so I can strongly type it?
You can’t change AutoQuery responses which are already fixed in their service contract definition to return a QueryResponse<T>.
You can add extra info to the Meta Dictionary of the Response DTO (exists for this reason) otherwise if you need to change the Service Contract you’d need to convert it into a normal (I.e. non-AutoQuery) API which could use the Service Gateway to call an existing AutoQuery API that decorates the response.
I am using Servicestack. I have a base class for my Services, like so:
public abstract class ServiceHandlerBase : Service
and then some methods and properties in there of interest. I already have several methods that accesses the IRequest object, like:
protected AlfaOnline GetContactItem()
{
string deviceUUID = Request.Headers.Get(Constants.DEVICE_UUID); // <-- calling this method from constructor will give NullRef on Request here
string authToken = Request.Headers.Get(Constants.AUTH_TOKEN);
// do stuff
return existingContactItem;
}
which works well inside my service implementations, no problems there.
Now, I wanted to use this exact same method directly from the base class, calling it in the constructor:
public ServiceHandlerBase()
{
AlfaOnline ao = GetContactItem();
}
but I then get a NullReferenceException on the Request object as noted above.
When is the Request object ready to access and use? Because it's not null inside the service implementations.
You can't access any dependencies like IRequest in the constructor before they've been injected, they're only accessible after the Service class has been initialized like when your Service method is called.
You can use a Custom Service Runner to execute custom logic before any Service is Executed, e.g:
public class MyServiceRunner<T> : ServiceRunner<T>
{
public override void OnBeforeExecute(IRequest req, TRequest requestDto) {
// Called just before any Action is executed
}
}
And register it with ServiceStack in your AppHost with:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext ctx)
{
return new MyServiceRunner<TRequest>(this, ctx);
}
But if you just want to run some logic for a Service class you can now override OnBeforeExecute() in your base class, e.g:
public abstract class ServiceHandlerBase : Service
{
public override void OnBeforeExecute(object requestDto)
{
AlfaOnline ao = GetContactItem();
}
}
See ServiceFilterTests.cs for a working example.
If you're implementing IService instead of inheriting the Service base class you can implement IServiceBeforeFilter instead.
The new Service Filters is available from v5.4.1 that's now available on MyGet.
I am trying to inject the IApplicationConfigurationSection implementation into this MVC5 Controller, so that I can have access to some of the information (various strings) from my web.config custom section in all of my views:
public class BaseController : Controller
{
public IApplicationConfigurationSection AppConfig { get; set; }
public BaseController()
{
ViewBag.AppConfig = AppConfig; // AppConfig is always null
}
}
I want to use setter injection so I don't have to clutter up my derived Controller constructors with parameters that they don't really care about.
Note: If there is a better way to inject base class dependencies, please let me know. I admit I may not be on the right track here.
In my Global.asax I load my StructureMap configurations:
private static IContainer _container;
protected void Application_Start()
{
_container = new Container();
StructureMapConfig.Configure(_container, () => Container ?? _container);
// redacted other registrations
}
My StructureMapConfig class loads my registries:
public class StructureMapConfig
{
public static void Configure(IContainer container, Func<IContainer> func)
{
DependencyResolver.SetResolver(new StructureMapDependencyResolver(func));
container.Configure(cfg =>
{
cfg.AddRegistries(new Registry[]
{
new MvcRegistry(),
// other registries redacted
});
});
}
}
My MvcRegistry provides the mapping for StructureMap:
public class MvcRegistry : Registry
{
public MvcRegistry()
{
For<BundleCollection>().Use(BundleTable.Bundles);
For<RouteCollection>().Use(RouteTable.Routes);
For<IPrincipal>().Use(() => HttpContext.Current.User);
For<IIdentity>().Use(() => HttpContext.Current.User.Identity);
For<ICurrentUser>().Use<CurrentUser>();
For<HttpSessionStateBase>()
.Use(() => new HttpSessionStateWrapper(HttpContext.Current.Session));
For<HttpContextBase>()
.Use(() => new HttpContextWrapper(HttpContext.Current));
For<HttpServerUtilityBase>()
.Use(() => new HttpServerUtilityWrapper(HttpContext.Current.Server));
For<IApplicationConfigurationSection>()
.Use(GetConfig());
Policies.SetAllProperties(p => p.OfType<IApplicationConfigurationSection>());
}
private IApplicationConfigurationSection GetConfig()
{
var config = ConfigurationManager.GetSection("application") as ApplicationConfigurationSection;
return config; // this always returns a valid instance
}
}
I have also "thrown my hands up" and tried using the [SetterProperty] attribute on the BaseController - that technique failed as well.
Despite my best efforts to find a solution, the AppConfig property in my controller's constructor is always null. I thought that
`Policies.SetAllProperties(p => p.OfType<IApplicationConfigurationSection>());`
would do the trick, but it didn't.
I have found that if I discard setter injection and go with constructor injection, it works as advertised. I'd still like to know where I'm going wrong, but I'd like to stress that I'm not a StructureMap guru - there may be a better way to avoid having to constructor-inject my base class dependencies. If you know how I should be doing this but am not, please share.
While constructor injection in this scenario appears to be the better solution to the stated problem as it follows The Explicit Dependencies Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
The mention of only needing to access the AppConfig in your views leads me to think that this is more of an XY problem and a cross cutting concern.
It appears that the controllers themselves have no need to use the dependency so stands to reason that there is no need to be injecting them into the controller explicitly just so that the dependency is available to the View.
Consider using an action filter that can resolve the dependency and make it available to the View via the same ViewBag as the request goes through the pipeline.
public class AccessesAppConfigAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
var resolver = DependencyResolver.Current;
var appConfig = (IApplicationConfigurationSection)resolver.GetService(typeof(IApplicationConfigurationSection));
filterContext.Controller.ViewBag.AppConfig = appConfig;
}
}
This now makes the required information available to the views with out tight coupling of the controllers that may have a use for it. Removing the need to inject the dependency into derived classes.
Either via adorning Controller/Action with the filter attribute
[AccessesAppConfig] //available to all its actions
public class HomeController : Controller {
//[AccessesAppConfig] //Use directly if want to isolate to single action/view
public ActionResult Index() {
//...
return View();
}
}
or globally for all requests.
public class FilterConfig {
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
filters.Add(new AccessesAppConfigAttribute());
}
}
At this point it really does not matter which IoC container is used. Once the dependency resolver has been configured, Views should have access to the required information in the ViewBag
I got the following block
container.RegisterType<IService, ServiceA>("a");
container.RegisterType<IService, ServiceB>("b");
I want to have a Dictionary of type Dictionary<string,IService>.
I will receive service name by parameter in an API rest and my idea is based on that parameter get the implementation I need from the Dictionary.
I can't figure out how to inject the Dictionary (with the resolved classes inside) into my business class.
I want to do something like this.
private readonly IDictionary<string,IService> serviceDictionary;
public ClassConstructor (IDictionary<string,IService> dictionary)
{
this.serviceDictionary = dictionary;
}
You should not inject IDictionary<string,IService> into your component, but instead an application-tailored abstraction:
public interface IServiceProvider
{
IService GetService(string key);
}
This way you can create an implementation for Unity as follows:
public class UnityServiceProvider : IServiceProvider
{
public IUnityContainer Container { get; set; }
public IService GetService(string key) => Container.Resolve<IService>(key);
}
Now you can complete your registration as follows:
container.RegisterType<IService, ServiceA>("a");
container.RegisterType<IService, ServiceB>("b");
container.RegisterInstance<IService>(new UnityServiceProvider { Container = container });
container.RegisterType<ClassConstructor>();
If I'm trying to serialize a normal CLR object, and I do not want a particular member variable to be serialized, I can tag it with the
[NonSerialized]
attribute. If I am creating a table services entity, is there an equivalent attribute I can use to tell Azure table services to ignore this property?
For Version 2.1 there is a new Microsoft.WindowsAzure.Storage.Table.IgnoreProperty attribute. See the 2.1 release notes for more information: http://blogs.msdn.com/b/windowsazurestorage/archive/2013/09/07/announcing-storage-client-library-2-1-rtm.aspx.
There's no equivalent I know of.
This post says how you can achieve the desired effect - http://blogs.msdn.com/b/phaniraj/archive/2008/12/11/customizing-serialization-of-entities-in-the-ado-net-data-services-client-library.aspx
Alternatively, if you can get away with using "internal" rather than "public" on your property then it will not get persisted with the current SDK (but this might change in the future).
For version 2.0 of the Table Storage SDK there is a new way to achieve this.
You can now override the WriteEntity method on TableEntity and remove any entity properties that have an attribute on them. I derive from a class that does this for all my entities, like:
public class CustomSerializationTableEntity : TableEntity
{
public CustomSerializationTableEntity()
{
}
public CustomSerializationTableEntity(string partitionKey, string rowKey)
: base(partitionKey, rowKey)
{
}
public override IDictionary<string, EntityProperty> WriteEntity(Microsoft.WindowsAzure.Storage.OperationContext operationContext)
{
var entityProperties = base.WriteEntity(operationContext);
var objectProperties = this.GetType().GetProperties();
foreach (PropertyInfo property in objectProperties)
{
// see if the property has the attribute to not serialization, and if it does remove it from the entities to send to write
object[] notSerializedAttributes = property.GetCustomAttributes(typeof(NotSerializedAttribute), false);
if (notSerializedAttributes.Length > 0)
{
entityProperties.Remove(property.Name);
}
}
return entityProperties;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class NotSerializedAttribute : Attribute
{
}
Then you can make use of this class for your entities like
public class MyEntity : CustomSerializationTableEntity
{
public MyEntity()
{
}
public string MySerializedProperty { get; set; }
[NotSerialized]
public List<string> MyNotSerializedProperty { get; set; }
}