Which Authorize Attribute ?
System.Web.Http.Authorize
System.Web.Mvc.Authorize
using System.Web.Mvc // or
using System.Web.Http
A typical controller
[Authorize]
public class SomeController : Controller
We have controllers Annotated with [Authorize]
I just noticed that due to using namespaces the annotations technically refer to different attribute classes.
The project contains MVC controllers and WEBAPI controllers.
Which one should I use and why ?
What issues might we have if I dont fix this ?
You must use System.Web.Http.Authorize against an ApiController (Web API controller) and System.Web.Mvc.Authorize against a Controller (MVC controller). Since the framework runs the filters as part of the pipeline processing and the controllers expect the right filter to be applied, if you don't use the corresponding filter, authorization will not work.
Related
I'm using Spring MVC through Spring boot starters (1.3.2) and i saw a difference of behavior regarding which template engine i'm using.
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
// template file
registry.addViewController("/index").setViewName("index");
// static file
registry.addViewController("/login").setViewName("login.html");
}
}
If i used Freemarker as template engine, Spring mvc will take the file from resources/static for /login and in resources/templates for /index
Whereas, if i used Thymeleaf as template engine, Spring will take all the files (login and index) from resources/templates.
As far as I know, this paths depends of application properties. By default:
#for freemaker
spring.freemarker.template-loader-path=classpath:/templates/
#for thymeleaf
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
Full list of common application properties you can find here.
View controller does not change behavior. When you entered url, Spring looking for method of Controller or ViewController, which has suitable request mapping. If method found, Spring invoke it. After that, controller's method returns view name as string, and Spring ask for special bean, named ViewResolver, to find view with this name.
Since every template engine has own ViewResolver, and any ViewResolver has it's own setings (as I said above), they're looking for templates in different places.
For example, you're using Thymeleaf and entered as url something like: localhost:8080/index. First, spring will find controller method or view-controller mapped with index. After that, controller will return string index. Spring will ask for Teamleaf view resolver to find this view. According to default settings, view resolver will add classpath:/templates/ before view name, and .html after view name, and after that will try to open file with this name.
For my web application in grails I have 3 admin controlling domain classes and no need of special UIs. For this I have decided to use dynamic scaffolding.
static scaffold = true; is scaffolding only one domain class.
Is there any way to scaffold all these 3 domain classes with a single controller. ?
I have found the solution.
We can scaffold a domain class from another controller by mentioning the name of domain class needed to scaffold dynamically.
For example:
static scaffold = User;
This scaffolding is happening in run-time only. So if we need to avoid scaffolding and if we wish to add actions manually we can eliminate the above code of line.
Started writing a simple filter to pull some stuff from request on each action load, copied some code from other stackoverflows that looks like so:
public class TestKeyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext context)
{
if (context.Request.Properties.ContainsKey("test"))
{
// do stuff
}
}
}
Then added the attribute with the rest:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
GlobalConfiguration.Configuration.Filters.Add(new ElmahHandledErrorLoggerFilter());
filters.Add(new HandleErrorAttribute());
filters.Add(new TestKeyAttribute());
}
On run, results in this error:
The given filter instance must implement one or more of the following filter
interfaces: IAuthorizationFilter, IActionFilter, IResultFilter, IExceptionFilter.
Most of the links I've found relate to MVC 3, and this seems to work; I am however using MVC 4 and using Web API - is there some other way I need to register the attribute now?
Just a note: I don't want the filter attached to Web API controllers (adding it to GlobalConfiguration.Configuration.Filters does work, though), but rather the normal web controllers.
Edit: I know I can get this working by inheriting from IActionFilter instead and using OnActionExecuting, I'm just curious why this approach doesn't work, since a bunch of tutorials seem to say it should.
I had the same error and was puzzled as ElmahHandledErrorLoggerFilter does implement IExceptionFilter.
After investigation, I kicked myself, I'd added the filters.Add(new ElmahHandledErrorLoggerFilter()); to the MVC site config under the FilterConfig class. Adding config.Filters.Add(new ElmahHandleErrorApiAttribute()); instead to the WebApiConfig class works.
Note: I'm using WebAPi v1 here but I've configured a v2 project in the same way.
The reason this doesn't work is that your filter is a WebAPI filter, which is not interchangeable with Mvc filters. The Mvc and WebAPI FilterAttribute and related classes and interfaces have many of the same names (which is why the tutorials appear to say this should work), but they live in different namespaces. Mvc filter classes live in System.Web.Mvc and WebAPI classes live in System.Web.Http.
Further reading here: https://stackoverflow.com/a/23094418/22392
When using MVC4, the project where your custom attribute resides must contain a reference to the System.Web.Http.Common library. I added it to my project using NuGet and hey presto! the error goes away.
I am using Spring Portlet MVC and Websphere Portal for my portlet application. In my jsp:
<portlet:actionURL var="saveFinishUrl">
<portlet:param name="action" value="saveFinish" />
</portlet:actionURL>
Now, I have a controller class defined in my portlet.xml. In that class, I have a method called saveFinish annotated like this:
#ActionMapping(params = "action=saveFinish")
My question is that in the jsp there should be a mapping that maps the jsp to tejh controller class. Otherwise how does the portlet container know which controller class is supposed to handle the request?
I know that <portlet:actionURL will generate a url that will direct to the correct controller...but how?
Your jsp in portlet environment is served by a particular portlet.
In case of spring mvc the first jsp is decided by the controller that has a #RenderMapping for view mode.
Also you know that you can use the action attribute of potlet:actionURL tag to set the action, and then use it as a value of #ActionMapping annotation?
I've just started to use the VS 2012 RC, and I'm creating an ASP.NET MVC 4 web application in which I plan to provide both an HTML-based user interface and a WebApi-based programming interface.
For my HTML website, I have a controller and view for each of my models (MVC!), and the routing works "by convention" so that, for example, the URL /client hooks up to my ClientController. My ClientController derives from Controller.
For my API, I will create new controllers that derive from ApiController. I naturally want my API URLs to be similar to my HTML URLs, so I'd like the client info to be available at /api/client. However, with the by-convention routing, that would suggest that I need an ApiController named ClientController. And I already have a ClientController class.
How do I deal with this? Do I need custom routing? Do I put the API classes in different namespace so that I can give them the same name?
Update: this question seems to suggest that a different namespace for my API controllers is all I need: Mix web api controllers and site controllers
All it requires is for the controller classes to be in a different namespace, and all is well.
Using MVC areas would also work (as suggested in gordonml's comment), but this effectively puts the controllers in different namespaces, so it's a more formal way of achieving the same result.
You may take a look at the following blog post which illustrates how an Api controller could serve Razor views as well. Basically he uses the RazorEngine to parse the Razor view end serve it.
For anyone looking for step by step guidance on how to do this on WebApi project:
Create two folders / namespaces, namely: ControllersApi and ControllersWeb
Right click on ControllersWeb and go Add -> Controller and select MVC 5 Controller - Empty. This will add all other dependencies if you didn't have them in your WebApi project.
Your RouteConfig will now register those classes that inherit from Controller base class. You'll likely need to add link to default Controller, by editing defaults to say: defaults: new { action = "Index", controller = "Home", id = UrlParameter.Optional }
That's it, you can now run site and use both API and Web controllers.