Define the controller namespace based on URL parameter - asp.net-mvc

I'm working on a Web API with MVC4, and I'd like to make it backwards-compatible, as I don't control when the clients are updated.
In order to do that, I'm going to create controllers on different namespaces, something like MyApp.Controllers.v1_0.AccountsController and MyApp.Controllers.v1_1.AccountsController
Obviously, when I create both of them and try to access to an action, I get "Multiple types were found that match the controller named 'Accounts'"
Then, what I tried to do is writing my own IHttpControllerActivator, so that when Create is invoked, it returns one of them... but that doesn't work b/c it never gets hit, which makes sense as Create receives an System.Web.Http.Controllers.HttpControllerDescriptor that includes information about the controller it's about to use.
Also, I can't just name the controllers different (Accounts1_0Controller, Accounts1_1Controller), as when the activators returns Accounts1_0Controller, it says that its name is not "Accounts"... it probably gets its name as Accounts1_0.
Do you see any way of either:
Set the namespace from the url? so that I have the url /v1_0/SomeAction or /v1_1/SomeAction and it searches the controller on the appropriate namespace
Having multiple controllers with the same MVC name but different class name?
Hope the issue is clear enough.
Thanks!

Fixed it implementing my own IHttpControllerSelector. It's great how Microsoft made MVC4 open source, made it almost painlessly looking at their System.Web.Http.Dispatcher.DefaultHttpControllerSelector.

Related

How to force one method on Razor ambiguous reference?

On one MVC 4 project, we have a lot of Pages.cshtml that receive a collection of Models (generally hundreds of rows), which we serialize as JSON via
#Html.Raw(Json.Encode(Model));
The problem is that on some of those pages we are receiving an exception (The length of the string exceeds the value set on the maxJsonLength).
We know what is the reason and how to fix it. The thing is that I would like to create a similar Json.Encode() method (using Json.Net), so we do not need to modify all the cshtml pages. If I create a Json.Encode() method, Razor complains about ambiguous reference between My.Namespace.Json and System.Web.Helpers.Json.
Again, we know how to solve this by adding an alias on the page:
#using Json = My.Alias.Json
What I'm trying to do is to transparently instruct Razor to choose this alias for all the cshtml pages that uses this Json.Encode. The reason is that I want this to be transparent, so later if somebody adds a new page, automatically he will start to use our custom JSON implementation.
I think on Views/Web.config you can add namespaces and some configurations for Razor, but I don't see how to explicitly set the aliases.
Interesting issue, but as far as I know that's not possible. See e.g. this: C#: Globally alias a generic class name?
As an alternative you could create a helper method Html.JsonEncode() and teach, drill or entice everyone to use that.
If you make it also do the Raw() call and return IHtmlString, then you can do #Html.JsonEncode(Model) as opposed to #Html.Raw(Html.JsonEncode(Model)) and before you know it everybody is a fan of your new method.

Do Actions in RCAV = Model in MVC? (Rails)

I'm trying to better understand the Rails workflow, specifically RCAV in relation to MVC. I know that MVC is the typical structure of a Rails app and that RCAV is the standard order of building various components of the app, however, I'm a little confused about the correlation between the two.
For example, I'm assuming the routes in RCAV are what link the models with views and controller in MVC. Is this correct?
I'm also guessing that the controller and view in RCAV are the same as the controller and view in MVC and simply represent the order in which you build them. Is this correct as well?
What I'm really stuck on is the Action part of RCAV - does this represent the Model component of MVC?
Sorry if my question doesn't make sense, just trying to get a better hang of the standard Rails workflow and the order in which various components of an app are typically built. I wish it were a little more distilled i.e. "first build Model, then Views, then Controller" but this whole separate RCAV thing is confusing me a little.
To your title question, no.
To elaborate, it's kind of confusing to map out RCAV (the sequence) against MVC (the framework), but I'll see if I can clarify. It's worth noting that the concepts themselves are not as complex as they seem, it's just confusing to explain.
RCAV
(Route-Controller-Action-View)
Routes are defined in config/routes.rb. You may think of them as the coupling between an HTTP Request and a Method (a specific type of method called an Action). On the one side it defines a path (ex. "/login") and one of the HTTP verbs (ex. "GET"), and says that whenever that type of request is made to that location, to perform the appropriate action. On the other side, an action is given in the form of the name of its controller (ex. "sessions"), and the name of the method itself (ex. "new").
Controllers receive the request according to the routes (so following the above example, if a user navigated to www.example.com/login, they would wind up in the sessions controller, which would be housed in app/controllers/sessions_controller.rb). The Controller may perform a number of functions prior to (and following) the action, in the form of callbacks. Callbacks are arguably a more advanced concept than what you need to understand right now, they are an important step (and the reason I explain RCAV as "Route >> Controller >> Action >> View", not as "Route >> Controller-Action >> View").
Actions are public methods in the Controller. Again, by our above example, you'll be hitting a method named "new" in the sessions_controller when a user navigates to www.example.com/login. Actions may perform any variety of functions, and there is often interaction with the model here (for instance, you may have a session model in app/models/sessions.rb with a method named "logout", and perhaps the first thing you do when you hit the login page is ensure the user is currently logged out by calling Session.logout. This is a poor design, but a decent example). Your action must "return" in one way or another. Assuming your action is meant to be consumed by a user directly through their browser (as opposed to as, say, a JSON or XML service), you will either render a view now, or redirect_to another action.
Views are, dare I say, the "end result" of the action. If nothing is specified, the above example will end by rendering "app/views/sessions/new.html.erb" for the user (Rails defaults to rendering the view whose path matches the controller and action, but as referenced above you could name something different). In this file you will also potentially make reference to the model associated with sessions (but this time inside of ERB tags, to be compiled into HTML).
MVC
(Model-View-Controller)
Models are classes tied, generally, to tables in a database. They contain validations for their fields, class methods, and instance methods. Say your database keeps track of sessions. Then you could potentially grab a list of sessions by calling Session.all anywhere in your application. You'd probably use an action in the Sessions controller to save this list to an instance variable (maybe #sessions), which could in turn be accessed in its appropriate view (<% #sessions.each do |s| %> ... <% end %>).
Views are essentially the web pages. They can bring along their own styles and scripts, and exist in the form of HTML files with embedded ruby. They are the end point of request made to your site (unless you're hitting a service which returns something like JSON or XML instead).
Controllers contain all the actions a user may access, often prepare variables via methods from the models, and generally drop the user into a view.
In Summation
A user accesses a route. The route drops them into a specific action within a controller. The controller (in the form of callbacks) and the action (on its own) prepare data from the model (via instance variables) to be consumed by the view. The view is then rendered into the users browser.
This is a simplification, but in the most standard cases, this is how the MVC framework (and rails, specifically) functions.

ASP.NET Web API with MVC: Attribute routes ignored in class libraries

I am developing an MVC application which makes use of plugins. I need to support using Web API from those plugins. I have it working (including Dependency Injection with Autofac as well). However, it seems like Attribute routing is completely ignored from the class libraries (plugins or any other assembly). For example, I have a test plugin specified as such:
[RoutePrefix("api/cms/test")]
public class TestController : ApiController
{
When browsing to /api/cms/test, I get the following error:
"No HTTP resource was found that matches the request URI '[my site]:30863/api/cms/test'.No type was found that matches the controller named 'cms'."
When I remove "cms", it works because it is then using the default route. Obviously this is not adequate, because I will very likely have multiple controllers with the same name (in different assemblies) and therefore need a unique route to each of them.
I inspected the Route Collection in System.Web.Http.GlobalConfiguration.Configuration.Routes as well to confirm and the route is indeed missing.
Is there anyone who can tell me why the attribute routes are being ignored for class libraries and if there's a workaround?
EDIT
Thanks to Kiran for the comment about the Route attribute; I did notice my error with forgetting the [Route("")] attribute on the controller which is to be used along with the [RoutePrefix] attribute. I added that and now attribute routing works fine. However, I still cannot have 2 controllers with the same name, even though they are in different assemblies. After doing some research it seems that this is a known issue - not just with different assemblies, but different namespaces in general. I tried to implement a solution from here:
http://shazwazza.com/post/multiple-webapi-controllers-with-the-same-name-but-different-namespaces/
The problem with this is that now the DataTokens is null AND read-only! So it is no longer a viable solution to this problem. Hoping someone else has a solution to this problem.
EDIT 2
Thanks to Kiran for his mention about route constraints. However, that still doesn't solve my problem. What I am looking for is a way to allow multiple controllers to have the same name whether they be in separate areas, separate namespaces or both.. whatever.. The problem with this is that the underlying Web API implementation looks up controllers by name using an IDictionary<string, HttpControllerDescriptor> variable to store such information. You can see this if you look at the source code for DefaultHttpControllerSelector. So, at first I thought maybe I just need to inherit this class and override GetControllerMapping() because the calling code in the internal class, AttributeRoutingMapper doesn't care about the keys in that dictionary at all... it only looks at the values. So at first I thought I could override this and use the full name of the controller (including namespace) as the key, so we can get them all in there. However, it is not that easy.. for a couple of reasons, not least of which is the fact that AttributeRoutingMapper is not the only class to call GetControllerMapping().
So it looks to be a lot of work to get what I need done; if is it even possible at all. I will be starting a bounty; 100 points to anyone who can provide a fully working solution or who can provide enough info for me to start a solution myself.
From the error message, looks like the order of routes are not correct...looks like your request is being matched by a conventional route (ex: api/{controller}) rather than the attribute route...as you know route order matters...so make sure to have attribute routes register before conventional routes as they are more specific...
Also note that RoutePrefix attribute alone doesn't add routes to the route table, but the attribute Route does...
I am guessing you are hosting your application in IIS?

Where should I create an action to populate a select?

I'm quite new to Rails development and I came up with this question today. I have a method that returns some JSON data.
It is used to populate a select with a list of cities according to what was selected on a previous select (list of states). So, it's a simple method that loads a list based on some ajax parameter passed through and it is used all along my site.
I'm using Rails 4 and I placed this method on my HomeController. So everytime I need to fetch the list of cities, I call the HomeController to load the data.
Is this the correct approach or should I place this method on a more generic controller (like ApplicationController)? Is there a better way?
I think the best thing is to keep this modular. So you can create a separate controller for this, like StatesController - and possibly even a separate model if that makes sense for your application (I'm not sure where you're getting your data). There is no cost to having extra controllers, and this way your code is clean and organized, with each piece of functionality existing in its logical place.

Finding the controller that called my controller; or traversing the Controller/Action stack

I'm using Html.RenderAction, in ASP.NET MVC (futures), to display modules on different pages.
I want the modules to be aware of which page they belong to (for settings and logging purposes).
Is there a way to get the Controller/Action - stack, on the current controller?
I found on the Controller base something called DescriptorCache under ActionInvoker and that has something called Cache wich has that info, however I do not have access to that in the Controller because it's defined as private.
Appreciate your help
:m
Can you? Yeah. Should you? Hell no. If you need to conditionally render, put the data into the view's model. Don't try to use the call stack as part of your view model!

Resources