Umbraco MVC Implementation - View does not depend on Umbraco implementations - asp.net-mvc

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.

Related

Why Orchard doesn't have model view controller?

I am working with orchard. writing such a project is my dream!.. so i started a research a bout that. which interested me about orchard, is while orchard is mvc project but why it doesn't have any model , view and controller in his web layer solution? does it use CleanArchitecture or some specific architecture like this ?
i tried to know about this case in orchards documents but i didn't find any description about it.
Actually, Orchard being an MVC based project, it intrinsically does have models, views and controllers. But it provides much more than that.
The key thing to understand, in my mind, is that at the very core, requests are handled by a given controller, which builds a model, and returns a view that uses this model. What Orchard adds to that is how it builds up a particular model, and how it selects the view to display that model.
Consider requesting a content item by navigating to, say, a content item with alias "/about".
What happens is that the ASP.NET routing will kick in, which has been configured to match against aliases of all content items. The route for "/about" will be found, which is handled by the ItemController of the Contents module (modules in Orchard are conceptually the same as MVC areas). The ItemController will build a dynamic model for the requested content item, which is called a shape. The shape is an instance of the Shape class, which contains metadata about the shape, such as the name of the shape. Based on this information, Orchard leverages the view engine to select the appropriate Razor view to render the shape object.
So you see, all of the basic MVC stuff comes into play. Orchard simply adds a powerful infrastructure on top of it to provide an advanced and flexible rendering system, like turning content items into shapes, which are then turned into HTML via the view engine. But at the end of the day, it's primarily about controllers creating models used by views.

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();

MVC partial views, partial model, partial controller?

Currently i am investigating if MVC is the way to go for the new major version of our web application. We have an existing web application with webparts, dynamically rendered according to some user settings. Each webpart has its own data and own logic (for example, one webpart with user information, one webpart with currently logged-in users, one webpart with appointments etc. etc.).
What we need to accomplish (i think) is to render a single view, which contains several partial views. Each partial view represents a different model, and has its own logic.
I figured out how to put multiple partial views within a single view, but i don't know how to handle the business logic for each view (in "partial controllers"? if possible at al?), and handle the model for each view?
So the main purpose is to render a page with multiple dynamic views (according to what the user has configured), each with its own logic and data. And then when, for example, a button is clicked in a partial view, the corresponding controller is called to handle the event, and returns the updated partial view. The partial views need to be loosely coupled, and updated async.
From what i've seen so far the most tutorials and documentation are focussing on MVC in general, not on how to separete the business logic and model for eachr partial view.
So I'm not asking how to do this, but:
Is it possible to easy accomplish this with MVC 4 or 5?
Does anybody know a good real-life example or tutorial about this?
I hope anyone can point me in the right direction or share some thoughts on this...
You could make one or more controllers with an action for each webpart.
Group all related webparts in the same controller but make an action and View+ViewModel for each webpart. Then use the Html.RenderAction method to call these actions (and have your webparts placed) on your page/main view.
DISCLAIMER: This said, each call to Html.RenderAction creates a complete mvc flow, instanciating a controller, model and view and finally renders the whole thing and passes the value to your page/main view. Having lots of Html.RenderAction has the potential to slow your page creation a lot. You could look into DI/IoC like Unity and consider reusing controllers, or just look into System.Web.Mvc.DependencyResolver to handle the creation of controllers yourself.

struts 2 actions coupled to pages?

Problem
While developing struts2 application I was asked to implement two pages: the one listing current user's books and the other listing current user's CDs. So I decided to implement two struts2 actions: ListBooks and ListCDs, both of them having standard dispatch result type, pointing to corresponding JSP pages.
Later the client changed his mind and decided that both lists of books and CDs should reside on the same page. So how can I reuse my actions so that I wouldn't need to rewrite any classes.
My attempt
First approach was to use action chaining. So that both actions can contribute their properties to value stack. But then there is a problem: we establish some unnatural order for actions. If I chain ListBooks to ListCDs then invoking ListCDs on its own causes some erroneous behavior - as it will result in a page where both books and CDs should be listed.
Another way was to use action tags. But I don't like it either as it forces separation of my page into multiple JSP parts and generally feels like doing things not in struts2 style.
Questions
So how do I combine my actions to form single page in a "clean way"? The problem seems to be so simple.
Another question spawned by this problem is about struts2 design - do struts2 actions take too much responsibility? Apart from being "single units of work" they are also coupled to presentation level. Everytime I change the structure of my pages I have to think about redesigning my actions. Am I missing something or struts2 really has this type of design weakness?
Struts 2 actions only take too much responsibility if they're designed that way--they should act as a thin bridge between the web and business layers.
Each of the earlier actions should have just had a service to retrieve the items in question. The new action would have both services, and expose the results of the user's books and CDs to the view layer.
Of course they're coupled to the presentation level--they are what determines what's available to the view. In any action-based framework this is the case, whether it's the action itself, the model in a ModelDriven action, a Spring MVC controller returning a view, a Struts 1 action form, request attributes, etc.
The amount of work necessary to support the type of change you describe is almost nothing: move the service from one action to another, and either expose the additional results directly, or add them to the exposed model.

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.

Resources