How is the default item controller registered/invoked in Orchard CMS? - orchardcms

I'm trying to get my head around how multi-tenancy and routing works in Orchard CMS.
As I understand when Orchard starts a new shell (tenant) all the active modules for that tenant are loaded and any modules that implement IRouteProvider "publish" their routes. A ShellRoute is then added for each route which will only be matched for requests made to that tenant's hostname/suffix.
The request is then handled in the normal way by MVC (looking in RouteTable.Routes for a match).
What I can't figure out is how the default ItemController is invoked since I couldn't find a default route for this in the source. Also I notice when browsing to the home page, the id route parameter is populated with that of the home page content item so I'm assuming there is some kind of pre-processing going on before the controller is hit?

There is a default IRouteProvider - Orchard.Mvc.Routes.StandardExtensionRouteProvider. It's responsible for registering default routes to controllers in form {module}/{controller}/{action}/{id}.
And yes, you're right - there is some preprocessing going on. A brief explanation:
Each item permalink (we call it an alias) is mapped to a route
that points to an action responsible for displaying it. By default -
Contents/Item/Display/{id}. Those mappings are kept in the database (AliasRecord and ActionRecord).
There is a special Route implementation - AliasRoute. This route is then registered once for each module and handles requests that match existing aliases. It all happens in Orchard.Alias module.
If the incoming request matches any alias, the call to AliasRoute.GetRouteData returns the underlying mapping. This way ASP.NET MVC framework knows which action to call.

Related

Customizing Zuul url endpoints for services in JHipster

I have a group of microservices, called "client-Foo", where Foo is the name for some particular third-party client.
Using those names as-is creates some really ugly endpoint urls, so I want to translate them to a much nicer hierarchal form.
I added a custom PatternServiceRouteMapper that take the serviceId client-Foo and turns it into the url client/Foo.
This gives the url I want, but also breaks the service mapping because it also changes the registered serviceId to client/Foo; thus, when Zuul goes to route it fails because there is no client/Foo service, its id is client-Foo!
I cannot hardcode any paths because the application requires an arbitrary number of different "client-*" services.
By looking at ZuulProxyAutoConfiguration, you can see that you can replace some beans to achieve your goal and in particular you should consider providing your own implementation of RouteLocator interface or extend DiscoveryClientRouteLocator class.
Your service instances could also register in Eureka server with additional data in metadataMap that your RouteLocator could use.
I would simply add a configuration defined Zuul route :
zuul:
routes:
client-foo: /foo/**
Also I would advise against having a dash in a service-id as it can confuse the config server api (in /config/foo-profile.yml where profile is the spring profile for which you want to get the config).

Refreshing with Browser History using React Router returns calls from my API

From what I understand, to use the browserHistory object in React Router properly, we need to use a wildcard * route so that the user is returned the single page application upon every refresh. Where this becomes a problem is when my client-side URL is the same as one of my api URLs.
For example, say I have a website called example.com and that one of the pages on this site is example.com/profile. If I refresh, the expected behavior is that it will simply reload the website example.com and route correctly to /profile, since the wildcard route should have returned the client the single page application. Where this doesn't work is if I have an API route /profile, i.e. example.com/profile. Now when the user refreshes the page, instead of being returned the the profile page, they are instead returned a JSON response from my API.
Depending on the order in which the wildcard route is declared, I can either have the API response returned on refresh, or the single page app on refresh, but not both when the API url is the same as the client side browser url.
Are there any suggestions around this issue? My current solution is to migrate all of my API routes to have /api/ prepended to them.
You need to make sure your client routes do not collide with your API routes, and prefixing API routes with /api is a pretty standard way to handle this.
There's no real way "around" the issue other than making sure they don't collide – various workarounds might be possible, but it's going to be more clear for everyone involved if routes are unambiguous.

MVC5 how to make db calls for a layout page

I have a MVC5 app that is using layout page to control the header and footer ect. The layout page has some sections that are database driven such as the nav bar. I am not sure of the best practice for where to make these calls is. I can think of 2 ways but neither are perfect
Method 1: Pass in data with the pages view model. Don't like this approach has my homepage controller should only be concerned with homepage content, not the layout. This would have to be repeated for each and every view.
Method 2: Ajax to WebAPI controller. Kinda leaning towards this, although I think this means losing stuff like #URL and #HTML which are being used to create links and render custom content.
EDIT: Though of another method
Method 3: Load info into cache on Start. Since this is not info that changes often after initial setup and this code is displayed on every page, caching would be needed anyways.
You should call a controller method from within the view. On your view:
#Html.Action("MyAction", "MyController")
Make sure this action can find everything it needs without having to have values passed in, and you're set. We do this in several projects via service location and/or dependency injection.

Inserting parameter to a web service call in service stack

Lets say I have the Hello World web service defined, from the Service Stack examples, but instead of just calling it as /hello/{name}, I want to be able to call it as /hello/{name}/id, where I define id to be a separate parameter (by storing it in refId, within a CustomUserSession).
In other words, I want to split the authentication and the actual web service call into 2 parts, but I don't want to expose this id in the actual web service call, because this is private, only within my system. How would I go about doing this? My ideal workflow is:
client calls web service : /hello/{name}
authentication happens. As part of this authentication, I get hold of this secret id
I now call the web service as /hello/{name}/id
It's almost as if I want to call a web service from within another web service.
I apologize if this seems like a misguided question, but how can I go about achieving this workflow?
Thanks
I recommend taking a look at ServiceStack routing. Your service will only be called if it matches an existing route (or uses a pre-defined route) which means if you only had:
[Route("/hello/{name}")]
It wont match /hello/{name}/{id} and your service wont be called. To match that route you can either have an explicit route for it, e.g:
[Route("/hello/{name}/{id}")]
But this is public info which you're saying you would like to hide. The alternative is to use a wildcard route, e.g:
[Route("/hello/{name*}")]
Which matches any /hello/* route inc. /hello, /hello/foo, /hello/foo/id, /hello/foo/id/and/more/etc.
But what gets populated in your Hello.Name property would be foo/id which you'd have to detect and parse in your service.
An alternative is to supply the hidden id in a QueryString or POST'ed form parameter which you can use in ServiceStack to further populate any request DTO, e.g. using the original route:
[Route("/hello/{name}")]
Will let you call the service with /route/foo?id=secret which if your Request DTO had an id property will be populated with secret. If you didn't have (or want) to have an id property you can still access the param with:
base.Request.QueryString["id"];
base.Request.FormData["id"];
But since you want this to be hidden, you should probably avoid passing it in the url which is visible by everyone (inc. web proxies, http logs, and other middle ware). A better place to hide a param is to pass it as a custom HTTP header, e.g: X-id: secret which you can access in your service with:
base.Request.Headers["X-id"];

Using Gaelyk URL routing in a non google app engine application

I have a Groovy Web application which is NOT being deployed on Google app engine. (GAE) I have used Gaelyk before and I like the URL routing functionality described in their doc
How do I port over just the routing functionality from Gaelyk to my basic Groovy WEB application which is not being deployed on GAE?
Note 1: I also do not want to use Grails for this application.
Note 2: I dont mind including the gaelyk jar but I rather not include anything from GAE.
If you want to implement this yourself in your own non GAE framework, the best place to start would be the source...
To start with, you'll need a class that extends javax.servlet.Filter in Gaelyk, this is the RoutesFilter class
As you can see, in the init method of the Filter, this calls loadRoutes which loads your routes.groovy script via a GroovyShell.
This shell makes use of the other classes in that same package so that it ends up populating the List<Route> routes property in the filter with instance of the Route class.
The filter (when configured by web.xml) then intercepts all requests to the server checks the URI against each route in turn (by calling the forUri method for each route), and if a match is found, it redirects or forwards as required.
If no match is found the Filter calls the next filter down the chain in the web server's context.
Hope this answers your question

Resources