I have a base Controller on my ASP.NET MVC4 website that have a Constructor simple as this:
public class BaseController : Controller
{
protected MyClass Foo { get; set; }
public BaseController()
{
if (User.Identity.IsAuthenticated))
{
Foo = new MyClass();
}
}
}
However I cannot access User here. It's null. But on my inherited Controllers it's fine.
Thanks
Controller instantiation will occur before authorisation takes place. Even if your MVC application calls RenderAction() several times and you end up creating say, five different controllers, those five controllers will be created before any OnAuthorization takes place.
The best approach to deal with these situations is to use Action Filters. The Authorize Attribute is fired early and may well be suited to your situation.
First, let's create an AuthorizationFilter.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyClassAuthorizationAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Controller.ViewData["MyClassInstance"] = new MyClass();
}
}
}
Now let's update our Controller
[MyClassAuthorization]
public class BaseController : Controller
{
protected MyClass Foo
{
get { return (MyClass)ViewData["MyClassInstance"]; }
}
}
In this case I would override Controller Initialize method:
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
// User.Identity is accessible here
}
Related
PFB my code.
namespace ManualCSharpe
{
public class MyServices : Service
{
[Route("/L/hello/")] //RequestDTO one
public class HelloL
{
public string Name { get; set; }
}
[Route("/H/hello/")] //RequestDTO two
public class HelloH
{
public string Name1 { get; set; }
}
public class HelloResponse //ResponseDTO
{
public string Result { get; set; }
}
public class HelloServiceL : Service //Service One
{
public object Get(HelloL request)
{
return new HelloResponse { Result = "Low" };
}
}
public class HelloServiceH : Service //Service
{
public object Get(HelloH request)
{
return new HelloResponse { Result = "High" };
}
}
//Define the Web Services AppHost
public class AppHost : AppSelfHostBase
{
public AppHost()
: base("HttpListener Self-Host",new Assembly[] {typeof(HelloServiceL).Assembly, typeof(HelloServiceH).Assembly}) { }
public override void Configure(Funq.Container container) { }
}
//Run it!
static void Main(string[] args)
{
var listeningOn = args.Length == 0 ? "http://*:133/" : args[0];
var appHost = new AppHost()
.Init()
.Start(listeningOn);
Console.WriteLine("AppHost Created at {0}, listening on {1}",
DateTime.Now, listeningOn);
Console.ReadKey();
}
}
}
When I am tring to added two service then it is show below exception.
An unhandled exception of type 'System.Reflection.AmbiguousMatchException' occurred in ServiceStack.dll
Additional information: Could not register Request 'ManualCSharpe.MyServices+HelloL' with service 'ManualCSharpe.MyServices+HelloServiceL' as it has already been assigned to another service.
Each Request DTO can only be handled by 1 service.
I have below douts.
Here I have created two different DTO for Two Service. Why it is showing error like Each Request DTO can only be handled by 1 service. In simple word, Two route mapped with two DTO with two Service.
Can I create one route for multiple RequestDTO with multiple service? In Simple word, One Route/L/hello/ can be mapped with two DTO HelloL and HelloH.
You can't have Service class implementations nested inside another outer MyServices class:
public class MyServices : Service
{
[Route("/L/hello/")] //RequestDTO one
public class HelloL
{
public string Name { get; set; }
}
[Route("/H/hello/")] //RequestDTO two
public class HelloH
{
public string Name1 { get; set; }
}
public class HelloResponse //ResponseDTO
{
public string Result { get; set; }
}
public class HelloServiceL : Service //Service One
{
public object Get(HelloL request)
{
return new HelloResponse { Result = "Low" };
}
}
public class HelloServiceH : Service //Service
{
public object Get(HelloH request)
{
return new HelloResponse { Result = "High" };
}
}
}
Remove the outer MyServices class completely and just have the DTO's and Service classes directly under a C# namespace.
Also routes shouldn't end with a / suffix, so I'd change:
[Route("/L/hello/")]
to:
[Route("/L/hello")]
#mythz answer is correct for OP but I came here looking for an answer for a different situation which the cause was not particularly obvious - you will get this exception if you attempt to register the same assembly twice, for example, if you move a service implementation into the same assembly and were pulling it in like so:
public AppHost() : base("App", typeof(AdminService).GetAssembly(), typeof(InboundService).GetAssembly(),typeof(ProductService).GetAssembly())
For those of you who come here from a google search, a AmbiguousMatchException exception in ServiceStack can sometimes be triggered within ServiceStack but handled internally.
You can change your exception setting so it doesn't break on this exception.
I had changed my exception setting to break on all exceptions and this had me stuck for a while.
I am trying to learn IOC principle from this screencast
Inversion of Control from First Principles - Top Gear Style
I tried do as per screencast but i get an error while AutomaticFactory try create an object of AutoCue. AutoCue class has contructor which takes IClock and not SystemClock. But my question is , in screencast IClock is resolved with SystemClock while inside AutomaticFactory .But in my code , IClock does not get resolved . Am i missing something ?
class Program
{
static void Main(string[] args)
{
//var clarkson = new Clarkson(new AutoCue(new SystemClock()), new Megaphone());
//var clarkson = ClarksonFactory.SpawnOne();
var clarkson = (Clarkson)AutomaticFactory.GetOne(typeof(Clarkson));
clarkson.SaySomething();
Console.Read();
}
}
public class AutomaticFactory
{
public static object GetOne(Type type)
{
var constructor = type.GetConstructors().Single();
var parameters = constructor.GetParameters();
if (!parameters.Any()) return Activator.CreateInstance(type);
var args = new List<object>();
foreach(var parameter in parameters)
{
var arg = GetOne(parameter.ParameterType);
args.Add(arg);
}
var result = Activator.CreateInstance(type, args.ToArray());
return result;
}
}
public class Clarkson
{
private readonly AutoCue _autocue;
private readonly Megaphone _megaphone;
public Clarkson(AutoCue autocue,Megaphone megaphone)
{
_autocue = autocue;
_megaphone =megaphone;
}
public void SaySomething()
{
var message = _autocue.GetCue();
_megaphone.Shout(message);
}
}
public class Megaphone
{
public void Shout(string message)
{
Console.WriteLine(message);
}
}
public interface IClock
{
DateTime Now { get; }
}
public class SystemClock : IClock
{
public DateTime Now { get { return DateTime.Now; } }
}
public class AutoCue
{
private readonly IClock _clock;
public AutoCue(IClock clock)
{
_clock = clock;
}
public string GetCue()
{
DateTime now = _clock.Now;
if (now.DayOfWeek == DayOfWeek.Sunday)
{
return "Its a sunday!";
}
else
{
return "I have to work!";
}
}
}
What you basically implemented is a small IoC container that is able to auto-wire object graphs. But your implementation is only able to create object graphs of concrete objects. This makes your code violate the Dependency Inversion Principle.
What's missing from the implementation is some sort of Register method that tells your AutomaticFactory that when confronted with an abstraction, it should resolve the registered implementation. That could look as follows:
private static readonly Dictionary<Type, Type> registrations =
new Dictionary<Type, Type>();
public static void Register<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
registrations.Add(typeof(TService), typeof(TImplementation));
}
No you will have to do an adjustment to the GetOne method as well. You can add the following code at the start of the GetOne method:
if (registrations.ContainsKey(type))
{
type = registrations[type];
}
That will ensure that if the supplied type is registered in the AutomaticFactory as TService, the mapped TImplementation will be used and the factory will continue using this implementation as the type to build up.
This does mean however that you now have to explicitly register the mapping between IClock and SystemClock (which is a quite natural thing to do if you're working with an IoC container). You must make this mapping before the first instance is resolved from the AutomaticFactory. So you should add the following line to to the beginning of the Main method:
AutomaticFactory.Register<IClock, SystemClock>();
I want to access the calling Service from inside the ServiceRunner OnBeforeRequest()method in order to get to an object in the calling service class. In MVC, I can create a class BaseController that overrides OnActionExecuting() and I can get to Data easily. However, using ServiceRunner, since it's not derived from Service, I don't see a way to get to the Service object.
Sample service:
public class ProductsService : Service
{
private MyData _data = new MyData();
public MyData Data
{
get { return _data; }
}
public object Get(GetProduct request)
{
// ...
return product;
}
}
In my custom ServiceRunner, how do I retrieve the ProductsService object from OnBeforeRequest() so I can get to Data?
public class MyServiceRunner<T> : ServiceRunner<T>
{
public override void OnBeforeExecute(IRequestContext requestContext, T request)
{
// var productService = ?
base.OnBeforeExecute(requestContext, request);
}
}
After much digging, it looks like this cannot be done. The Service action is available in the ServiceRunner as an unnamed lamdba delegate. There is no reference to the Service.
I have instead found a workaround. I first registered MyData in AppHost.Configure() using
container.RegisterAutoWired<MyData>();
I moved the MyData declaration to a filter attribute like this:
public class UseMyDataAttribute : RequestFilterAttribute
{
public MyData Data { get; set; } // injected by Funq IoC.
public override void Execute(IHttpRequest req, IHttpResponse res, object responseDto)
{
Data.SessionID = req.GetSessionId();
}
}
This way I can apply [UseMyData] to the ProductsService class and be able to set the Session ID to Data.
I am trying to create a Custom Attribute for a ServiceStack Service with which I can control each method in the service Class.
This is the attribute class that I am implementing.
[AttributeUsage(AttributeTargets.Method|AttributeTargets.Class , Inherited = false, AllowMultiple = false)]
public class MyRequestFilterAttribute:RequestFilterAttribute
{
public string Provider { get; set; }
public MyRequestFilterAttribute(ApplyTo applyTo): base(applyTo)
{
this.Priority = (int) RequestFilterPriority.Authenticate;
}
public MyRequestFilterAttribute():this(ApplyTo.All)
{
}
public MyRequestFilterAttribute(ApplyTo applyTo, string provider): this(applyTo)
{
this.Provider = provider;
}
public MyRequestFilterAttribute(string provider): this(ApplyTo.All)
{
this.Provider = provider;
}
public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
{}
}
This is the Service Class
[MyRequestFilter(ApplyTo.All)]
public class TodoService : RestServiceBase<Todo>
{
public TodoRepository Repository { get; set; }
public override object OnGet(Todo request)
{
if (request.Id == default(long))
return Repository.GetAll();
return Repository.GetById(request.Id);
}
public override object OnPost(Todo todo)
{
return Repository.Store(todo);
}
public override object OnPut(Todo todo)
{
return Repository.Store(todo);
}
[MyRequestFilter("Admin")]
public override object OnDelete(Todo request)
{
Repository.DeleteById(request.Id);
return null;
}
public object GetDetailsofALL()
{
return null;
}
}
I am able to get control on the Methods when I place the attribute on the Class level.
i.e
[MyRequestFilter(ApplyTo.All)]
public class TodoService : RestServiceBase<Todo>{}
What I require is to place an attribute on the method level as well and do some authentication such that only an admin has the right to perform this method of the service.
But when I place this attribute in the Delete method it is not working and the custom filter attribute is not getting hit. Only the class level attribute call works.
[MyRequestFilter("Admin")]
public override object OnDelete(Todo request){}
Is it possible to set the permission/filter attribute from the method level? If yes, how can I implement this?
No it's not possible to add it on the method. You can add it on the service class or the Request DTO and use the ApplyTo method filter to tell servicestack which methods it should apply to, e.g:
[MyRequestFilter(ApplyTo.All)]
[MyRequestFilter(ApplyTo.Delete, "Admin")]
public class TodoService : RestServiceBase<Todo> { ... }
You can also refer to the implementation of the [RequiredRole] and [RequestPermission] attributes for examples of Request Filter attributes that support this.
I have a design issue that I encounter currently.
Let's say there is a hierarchy of components. Each of these component derives from an abstract Component type which looks something like this:
public abstract class Component
{
public abstract Component Parent { get; }
public abstract ComponentCollection Children { get; }
}
Now I want to add some optional functionality to those components, lets take being able to search within the component hierarchy and to select components within the hierarchy as examples.
Is it considered bad practice to provide those optional functionality in the base class like this:
public abstract class Component
{
// Other members
public abstract bool IsSearchable { get; }
public abstract bool Search(string searchTerm);
public abstract bool IsSelectable { get; }
public abstract bool Select();
}
While the "search-ability" and "select-ability" is managed in derived components by e.g. using strategy patterns?
Somehow this seems like violation of the SRP to me, but in my opinion the only alternative would be to have an interface for each optional functionality and only implement it on components that support this functionality.
In my opinion this would have the drawback that I have to write code like this everytime I want to check if a component provides specific functionality:
public bool Search(Component component, string searchTerm)
{
ISearchable searchable = component as ISearchable;
if(searchable != null)
{
searchable.Search(searchTerm);
}
}
Which strategy would you choose or do you have any better ideas?
Thanks in advance!
A possible option:
If the searchability/selectability implementation is provided through the strategy pattern (dependency injection), as you say, then I think interfaces for ISearchable and ISelectable are a better idea.
You can derive your strategy object from these interfaces, and implement getters for them in your base-Component class - GetSearchable(), GetSelectable() - where the default implementation in Component returns null (or a no-op implementation of the interface if you dislike null).
Why don't you use decorator?
Component c = new Component ();
var selectableAndSearchableOne = new SelectableComponent (new SearchableComponent (c));
Ok another one: this time you also know the component's extension points. with a visitor-like pattern
public interface IHasExtensions
{
List<Extension> Extensions { get; }
void Extend (Extension ext);
}
public class Component : IHasExtensions
{
List<Extension> exts = new List<Extension> ();
public List<Extension> Extensions
{
get { return exts; }
}
public void Extend (Extension ext)
{
exts.Add (ext);
}
void Draw() { }
}
public abstract class Extension
{
readonly protected Component _Component;
public Extension(Component component)
{
_Component = component;
}
}
public class SearchExtension : Extension
{
public SearchExtension (Component component) : base (component)
{
}
}
public class SelectionExtension : Extension
{
public SelectionExtension (Component component) : base (component)
{
}
}
public class test_fly
{
void start ()
{
Component c = new Component ();
c.Extend (new SearchExtension (c));
c.Extend (new SelectionExtension (c));
var exts = c.Extensions; // I Know the extensions now
}
}