Nested controllers in Umbraco - umbraco

I`m new with Umbraco so I'd like to know: Is it possible to create nested controllers in Umbraco? Is it possible to have several methods in the Render Controller?
I want the url like this:
http://www.HOST/dates/[date]/place/[placeId]/entities/[entityId]
Also I had to get data from the database on each level.

It's possible to do anything you can do with standard ASP.Net MVC; however you probably want to read up on Umbraco's controllers etc. and Route Hijacking here:
https://our.umbraco.org/documentation/Implementation/Controllers/
https://our.umbraco.org/documentation/Implementation/Custom-Routing/
https://our.umbraco.org/documentation/Reference/Routing/

Related

Working with non-Umbraco data in MVC and Umbraco project?

I am working on a project that has MVC 4 and the Umbraco CMS installed. I apologise - being newbie, my question may be weird.
My question is: how do I work with types which I don't want to manage through Umbraco back office?Rather, it will be simple data coming and being stored in SQL Server.
Specifically I want to ask:
Can I create a controller in MVC and bypass Umbraco?
What controllers should be inherited from? Should they be standard MVC Controller, SurfaceController or RenderMvcController? Again, it will not be an Umbraco document type or data.
Will views be inherited from UmbracoViewPage, UmbracoTemplatePage or it can be a standard MVC view?
How will the URL of these views, controllers and actions change? In Umbraco, the URL depends on the content tree, but how it will be with non Umbraco controllers, views and actions?
Thank you so much for your precious time, guidance, sharing and help; I highly appreciate it.
You are asking a lot of different questions here.
When developing with umbraco Umbraco it's not uncommon to embed external data into your website. If we already tell you that you can use (almost) any type of dataaccess you use in plain .Net projects.
Don't loose your umbraco context
It's important when pulling in external data (e.g.) products, that you don't loose your umbraco context. You still have a breadcrumb to render, css classes for active menu's to set and so on. Your "external data" belongs probably below a node. Therefor it's a bad idea to use Standard MVC controllers.
Dirty razor
Because your views are in razor, you COULD put every extraction of external data into #{ ... } in your view. If you are not an experienced programmer, this works. Although topics about maintainablility and DRY principles are questionable :-)
RenderMvcController versus SurfaceController
When you use a RenderMvcController you basically are are creating a Controller for a specific document type. Each time umbraco is rendering a node of this document type. This controller will be invoked and the model you render is send back to the View. As you might guess, this is one of my favorite places to extract data and push it to the view.
A surface controller on the other hand is a controller for a partial view, extremely well in handeling form postbacks.
Both of these controllers can be used for the front-end of your website, not for the backend.
Inherit your views
You can do with your views what you want. But if you inherit your view from UmbracoViewPage you still have all the #Umbraco.Whatever power available in your views
Your URLS stay the same
Because you "hijack" a route using the RenderMvcController, you can just trust the umbraco backend to go to the right URL. The querystring can be used to get external data you want.
Other controllers or methods
Sometimes, if I can't use the controller above, I create an extentionMethod on the IPublishedContent. Like that I can write code like this:
foreach (var myObj in Model.Content.GetMyExternalData()) {
// do stuff
}
Of if you need to expose data (using a webApi wrapper), try the UmbracoApiController. This REST pure sang.
Data Access in umbraco
You should know that Umbraco uses petapoco as ORM. Therefor you can (and should) consider to use it too. You can reuse the database connection without any problems.
var query = new Sql().Select("*").From("myCustomTable").Where<MyModel>(x => x.Id == id);
return DatabaseContext.Database.Fetch<MyModel>(query).FirstOrDefault();

Umbraco MVC Implementation - View does not depend on Umbraco implementations

I have followed this nice tutorial which explains how you can take even more advantage of using Umbraco as a content delivery system. Tutorial MVC Umbraco => Your model and views should not depend on specific Umbraco implementations which is a huge advantage for real front-end developers.
The controller inherited from Umbraco.Web.Mvc.RenderMvcController in order to access the data from the CMS.
Now my problem is that we can't use #HTML.actionlink for navigation, it seems that this is only supported in SurfaceController.
Now my question is how would we implement navigation inside Umbraco.Web.Mvc.RenderMvcController? Can we still use the native #HTML.actionlink tag?
No you can't. Simply because all requests pass through a single action. In order to retrieve a path to a CMS-managed page, you need to use the node/content traversal the #Model provides. See here for more details on this.
Edit
To clarify, the author of the article is suggesting that the Umbraco implementation should be more in line with a traditional MVC implementation with little or no logic in the views. Therefore, any querying of node data should happen prior to the view (e.g. in the Mappers). So this is where you would have to retrieve the links.
Umbraco's default MVC implementation forces all requests to go via a single action on a single controller. The author's implementation allows the requests to be shared across one controller per document type - which is better IMO. But it still means that things like Html.ActionLink are redundant in the views since there isn't an action per page.
Further edit
If you wanted to build a navigation list with a combination of Umbraco-managed pages and non-Umbraco pages, regardless of the implementation, I would:
Create a child action and view for the navigation in a separate NavigationController that inherits from the SurfaceController
Use the this.CurrentPage property of the inherited SurfaceController to traverse the Umbraco content cache to retrieve the relevant Umbraco-managed pages. You can then use the Url property of each page result to get its path, and the Name property to get the page title
Use this.Url.Action("action", "controller") to retrieve the paths to specific non-Umbraco actions. Alternatively, if the pages are database-managed, use you data layer (e.g. EF, NHibernate, PetaPoco) at this point
Combine these in a Dictionary to make the list you require where the Key is the path and the Value is the page title
Pass this down to the view as the view model.
Of course there any many more things to consider like caching, but in a nutshell, that's a fairly basic implementation.

ASP.NET MVC -URL structure recommendations

Is there any standard for setting up URL (Controller) structure? I usually look at my entities and set up a Controller for each entity I need to expose.
Is there any standard I am missing? Are there other choices?
The functionality, user experience and URL's should dictate your need for controllers, not the entities.
Look at Rob Conery's MVC StoreFront example - it's a E-Commerce website, and a perfect example.
He creates controllers based on functionality (CatalogController, ShoppingCartController).
Now a "CatalogController" might work with multiple entities, but the "Catalog" is the manager for these entities, much like an aggregate root in the persistence layer.
As for the URL's, this decision should come first, before you decide to create controllers.
Work out what URL's you would like to expose, then decide how to group these URL's into logical areas, then create controllers for each area.
It depends on problem you want to solve.
If you are creating controller with CRUDL methods for each entity consider use Dynamic Data

ASP .NET MVC correct UserControl architecture

I'm trying to learn the new ASP .NET MVC framework and would like to know the best practice for using UserControls.
I understand that you can render UserControl's as a partial and pass data to them from a controller. Ideally I would think that it makes sense not to have a code behind file as this creates a temptation to break the MVC rules.
I'll give an example where I don't understand how UserControls fit into the pattern.
I have a UserControl that shows the
latest tags (much like on
StackOverflow). Unlike StackOverflow I
want to display this UserControl on
all of my pages. If I have a
controller say QuestionController
which is meant to handle actions from
some question views e.g. view and
detail, does this mean I have to fetch
the data in the QuestionController and
then pass it to the UserControl?
If I create another controller say
SearchController then I would have to
replicate the same functionality to
get the latest tags to pass to a
partial again. Doesn't this mean that
the 2 different controllers are doing
extra things that they weren't
originally intended to do?
If your UserControl appears on every page, then one way to address this would be to use a base controller from which all of your controllers derive and generate the ViewData for the UserControl by overriding the OnActionExecuting method and putting the logic there. If your UserControl is less pervasive, but still frequently used throughout the site, you could extend ActionFilterAttribute and have your filter generate the needed data. This attribute could be used to decorate the controllers or actions that generate views that use the UserControl.
I'm assuming in all of this that the data for the UserControl is independent of the action being invoked. If there is a dependency, it's probably best to push the logic into a class (or classes, perhaps using Strategy) and make the generation of the data explicit in each action or controller (via overriding OnActionExecuting).
Alternatively, with ASP.NET MVC 2 you can now use RenderAction to call a completely new controller action which can fetch the data. This makes your code much more modular and it is more clear where the data is coming from.
You can also consider putting your model classes in an hierarchy. The upper class (or one of the upper classes) will contain data necessary for your pervasive user controls. Then you can load these commonly used data in a base controller class.

asp.net mvc - subfolders

How does the new Microsoft asp.net mvc implementation handle partitioning your application - for example:
--index.aspx
--about.aspx
--contact.aspx
--/feature1
--/feature1/subfeature/action
--/feature2/subfeature/action
I guess what I am trying to say is that it seems everything has to go into the root of the views/controllers folders which could get unwieldy when working on a project that if built with web forms might have lots and lots of folders and sub-folders to partition the application.
I think I get the MVC model and I like the look of it compared to web forms but still getting my head round how you would build a large project in practice.
There isn't any issues with organizing your controllers. You just need to setup the routes to take the organization into consideration. The problem you will run into is finding the view for the controller, since you changed the convention. There isn't any built in functionality for it yet, but it is easy to create a work around yourself with a ActionFilterAttribute and a custom view locator that inherits off ViewLocator. Then when creating your controller, you just specify what ViewLocator to use, so the controller knows how to find the view. I can post some code if needed.
This method kind of goes along with some advice I gave another person for separating their views out for a portal using ASP.NET MVC. Here is the link to the question as a reference.
In terms of how you arrange your views, you can put your views in subfolders if you'd like and create your own view structure. All views can always be referenced by their full path using the ~syntax. So if you put Index.aspx in \Views\Feature1\Home then you could reference that view using ~/Views/Feature1/Home/Index.aspx.
Here's two good blog posts that I found that may help other readers:
http://stephenwalther.com/blog/archive/2008/07/23/asp-net-mvc-tip-24-retrieve-views-from-different-folders.aspx
This one talks a little more in-depth about what Haacked described above.
http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx
This is a nice alternative for grouping your site into "areas."

Resources