Data Routing for MVC Functions

Use data URL mappers with data items rendered by MVC functions.

When MVC functions are used for rendering data items, registering a data URL mapper will allow synchronization between the tree view and browser view in the CMS Console.

You can registering a data URL mapping for MVC functions in one of the following ways:

  1. Using the [DynamicUrlMapping] or [GlobalUrlMapping] attributes for controllers registered with the [C1Function] attribute.
  2. Using AddUrlMapping(...) when registering controllers on the application startup.

1. Registering mappings with attributes

For MVC functions defined with the [C1Function] attribute, you can use the [DynamicUrlMapper] or [GlobalUrlMapper] attribute on an action method that renders a data item by a certain field.

  • DynamicUrlMapper registers a data URL mapper when a page is rendered. Mostly suitable for page folder data.
  • GlobalUrlMapper requires defining a page id, and is registered globally. Suitable for global data types, that do not contain a reference to a CMS Page.

DynamicUrlMapper:

  • [DynamicUrlMapper(type)] registers a URL mapping that uses the default "Id" field as the key, for links like: /pageUrl/<action>/<dataid>
  • [DynamicUrlMapper(type, "<fieldName>")] - registers a URL mapping that uses a specified field value as the key, for links like: /pageUrl/<action>/<label field>

GlobalUrlMapper:

Similarly GlobalUrlMapper allows associating between a global data type item and urls to a certain page:

  • [GlobalUrlMapper(type, "<pageid>")]
  • [GlobalUrlMapper(type, "<pageid>", "<fieldName>")]

Example

The following is the example of registering an URL mapping for a controller exposed as an MVC function.

A custom data type ICar is used for this example.

Show the sample code for ICar

Controller:

using System.Linq;
using System.Web.Mvc;
using Composite.AspNet.MvcFunctions;
using Composite.AspNet.MvcFunctions.Routing;
using Composite.Core.Linq;
using Composite.Core.Routing.Foundation.PluginFacades;
using Composite.Data;

namespace Composite.Demo
{
    [C1Function(Namespace = "Demo", Name="Car")]
    public class CarController: Controller
    {
        public ActionResult Index()
        {
            var cars = DataFacade.GetData<ICar>().ToList();

            return View(cars);
        }

        [GlobalUrlMapper(typeof(ICar), "c5383680-45b7-4a96-9f8d-be4910522221")]
        public ActionResult Details(string id)
        {
            var car = DataFacade.GetData<ICar>().FirstOrDefault(p => p.Id == id);

            return car == null ? (ActionResult) HttpNotFound() : View(car);
        }

        [GlobalUrlMapper(typeof(ICar), "c5383680-45b7-4a96-9f8d-be4910522221", "Name")]
        public ActionResult DetailsByName(string id)
        {
            string name = id;

            var product = DataFacade.GetData<ICar>().Evaluate().FirstOrDefault(p => LabelToUrlPart(p.Name) == name);

            return product == null ? (ActionResult)HttpNotFound() : View("Details", product);
        }

        private static string LabelToUrlPart(string partnerName)
        {
            return UrlFormattersPluginFacade.FormatUrl(partnerName, true);
        }
    }
}

Download the code

Make sure to register your controller as an auto-discovered MVC Function.

Show the sample startup handler code for CarController

You should also create corresponding views in /Views on your website.

Views:

  • ~/Views/Car/Index.cshtml
@model IEnumerable<Composite.Demo.ICar>

@if (Model != null)
{
    <h1> List of cars: </h1>
    
    foreach (var product in Model)
    {
        <div>
            @Html.ActionLink(product.Name, "Details", new {id = product.Id})
        </div>
    }
}

Download the code

  • ~/Views/Car/Details.cshtml
@model Composite.Demo.ICar

<h1>Car information:</h1>

<p>
    Model: <strong>@Model.Name</strong>
</p>
<p>
    @Model.Description
</p>

<br />
<p>
    @Html.ActionLink("Go back", "Index")
</p>

Download the code

2. Adding data URL mappers for controllers registered as functions

If you choose to register your controllers on the application startup, you can add data URL mappings with a call to the extension method AddUrlMapping.

For example, for a link like <pageUrl>/details/{id}, the call would be:

functionCollection.RegisterController<ProductController>("Demo.Product")
    .AddUrlMapping<Product>(new Guid("3a613405-9990-47a6-8f00-672a8e6de9e7"), "details");

For controller-based MVC functions, you have to manually specify action name if it appears in URLs.

For action-based MVC functions (defined with the RegisterAction method), you don't need to specify the action name for data URL handling.

Requirements

  • C1 CMS version 5.0 or later