📜 ⬆️ ⬇️

Screw Umbraco CMS as a source of content



Target audience : systems that need a simple CMS that does not affect the architectural solution. (CMS, as content repository, without generating forms, etc.)

The purpose of this article is to show in “2 words” how Umbraco CMS can be used as a data source on which the main application globally does not depend (after all, the source can be replaced with any other), in other words, how to put the CMS into a separate project .
')
Some time ago I found out about Umbraco CMS, which immediately caught my attention. One of its main advantages for me was its free openSource, with all that it implies. Rather simple and effective design, simple background, large community and a wide range of free extensions. A complete list of advantages and disadvantages can be found online. I was upset only two points:

  1. CMS makes certain claims to the structure and platform of the main application, routing, etc. Programming in C # comes down to writing User Controls.
  2. Based on the first point, at the moment the latest version (4.10) cannot be used with ASP.NET MVC, which I love so much. (I saw a version with a “mixed type” project - ASP.NET + ASP.NET MVC, but I didn’t like it either)

I also wanted to use CMS exclusively as a content administration module, the data of which I could get by simply connecting a couple of libraries to any other project. And, as far as I understand, Umbraco does not provide such an opportunity to silence. In addition, I would like to write the page layout myself, the logic of data binding in C #, determine the layout, do not mess with xslt, on which the ui-engine umbraco is built. After spending some time in search and not finding anything suitable, I had to solve this problem myself.

It is worth noting for the sake of fairness that as a result, some CMS functions will be unavailable due to the fact that the main application is not integrated into it. For example: creating and editing pages, administering themes, scripts, macros. Anyway, the default. So, if you need a full-featured CMS, in which the client should be able to perform all these actions, then this option is not very suitable.



Schematically it looks like this:


So, first you need to do the following:


  1. Creating a CMS project
    • Since umbraco is written in ASP.NET, in VisualStudio we create an empty project of the appropriate type (we delete all files and folders from it)
    • We install in this project “Umbraco Cms” from NuGet.
    • Start the project - the Umbraco configuration start page will open, where we link it to the database.

  2. Umbraco extension
    Background:
    When using cms in a separate project, there is one significant nuance that requires some additional gestures, namely: since it is already impossible to do something like umbraco.GetCurrentItem () in a web application, because its context is not tied to cms, you need to somehow get the nodes we need.
    Umbraco.API makes it possible to do this on several parameters of the node, none of which up to the end guarantees that we will receive exactly that node, or we will receive something in general.

    It would seem that getting the node by its ID is the ideal solution - you can hard-code the necessary IDs and do uQuery.GetNode (int nodeId) quietly, but umbraco implements the through-numbered nodes, and, as far as I understand, they are not implemented if you install the package with the same nodes. Therefore, in order to minimize the work related to finding the right nodes in the future, the following mechanism is implemented:



    The figure shows the implementation of custom controls for Umbraco. The control is responsible for setting associations between the cms nodes and custom enum from the web application (DropDown is mapped to enum, the node is selected via the ContentPicker). This is the simplest implementation of the concept, i.e. instead of enum, the list of node names can have any structure and is stored not only in enum. For example, if in the application you need to know about 100 nodes, and not about 10 - you can think of something more complicated. By the way, this way it is possible to implement the localization of a web site by adding sets of associations for different cultures (arrow Ru-Ru). Before saving the data from ContentPicker, we get the real node ID.

    Also, with a strong desire, you can check here whether the nodes from umbraco that were expected in the web application have disappeared, display warnings, write mails, etc., anticipating the appearance of NotFound errors.

    These associations are stored in the Umbraco database (for example). In the simplest case, the table has the following structure:



  3. Setting up a web project
    Now for the main consumer project. In order to get the data saved via cms via Umbraco api, you need to do the following:
    • Copy config \ umbracoSettings.config from the root cms to the root of the web project
    • Set the value of the “ XmlContentCheckForDiskChanges ” property in this config to true (this item is optional, but will give an opportunity to instantly pick up changes in cms)
    • Copy the keys from the web.config cms to the project web.config:
      • " UmbracoDbDSN " - the path to the cms database
      • “ UmbracoContentXML ” is the path to the xml file where cms caches data. More precisely: the default file is located in " \ App_Data \ umbraco.config". There is a nuance. If the cms is physically located on another server, then the solution of the problem requires additional actions. I did not delve too deeply into the umbraco caching mechanism, but I think that if necessary, caching to the file can be completely abandoned.
      • Add references to the following assemblies:
        • businesslogic.dll
        • cms.dll
        • controls.dll
        • interfaces.dll
        • umbraco.dll
        • umbraco.DataLayer.dll



    4. Access to data
    If I didn’t miss anything, it’s enough for api umbraco to work as it should. To get the desired node, you need to know its Id. All you need to do is get the desired Id from the ItemsIdMap table of associations by the name of the enum element and culture, if any. For example:

    ItemsIdMap itemAssociation = context.ItemsIdMaps.SingleOrDefault(p => p.ItemCID == CmsItemCID.News.ToString() && p.Lang == "Ru"); Node node = uQuery.GetNode(itemAssociation.ItemId); string content = node.GetProperty(propertyName).Value; 



    That's basically it. An example of this conceptual, in the process there are various nuances, but that's another story - everything is solved as they become available. I also note that I myself have not tested this solution myself either for all possibilities or for performance. By the way, in this case, it is convenient to download the source code of Umbraco, temporarily connect instead of builds and debug if there are any obscure problems because The use of cms is not typical. In any case, while I like this solution much more than writing the admin panel with my own hands.
    Thanks for attention!

Source: https://habr.com/ru/post/158587/


All Articles