Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Sam 23 posts 115 karma points
    Mar 06, 2020 @ 10:01
    Sam
    0

    Extending Umbraco with custom controller and routing

    Hello,

    When i call a partial it complains the Model isn't IPublishedContent?

    But when i tell my custom ViewModel to inherit from IPublishedContent like in the documentation, i get the following error:

    Err: 'No parameterless constructor defined for this object.'

    How do i fix this so i can use my partials?

    Code below:

    ViewModel:

    public class MainViewModel : ContentModel
    {
        //Constructor of MainViewModel
        public MainViewModel(IPublishedContent content) : base(content)
        {
            SiteSettings = new SiteSettingsViewModel();
            BusinessCentersData = new List<BusinessCenterDataViewModel>();
            BusinessCenterData = new BusinessCenterDataViewModel();
            SiteSettings = new SiteSettingsViewModel();
            UmbracoBusinessCenters = new UmbracoBusinessCentersViewModel();
            RawContent = RawContent;
            }
    
        //Independant View 
        public SiteSettingsViewModel SiteSettings { get; set; }
        public UmbracoBusinessCentersViewModel UmbracoBusinessCenters { get; set; }
        public List<BusinessCenterDataViewModel> BusinessCentersData { get; set; }
        public BusinessCenterDataViewModel BusinessCenterData { get; set; }
        public IPublishedContent RawContent {get; private set; }
    
        public string siteName { get; set; }
        public dynamic RootNode { get; set; }
    }
    

    Controller:

    public ActionResult BusinessCenters(MainViewModel model)
        {
            try
            {
    
                using (var cref = _context.EnsureUmbracoContext())
                {
                    //Content Cache
                    //var cache = cref.UmbracoContext.Content;
                    var cache = cref.UmbracoContext.Content;
                    dynamic rootNode = cache.GetAtRoot();
                    model.RootNode = rootNode;
                    //Call Any Missing Umbraco Content
                    IPublishedContent siteSettings = cache.GetSingleByXPath("//siteSettings");
                    UmbracoContentBuilderClass siteSettingsModel = new UmbracoContentBuilderClass();
                    model.SiteSettings = siteSettingsModel.PopulateSiteSettingsModel(siteSettings);
    
                    IPublishedContent businessCenters = cache.GetSingleByXPath("//businessCenters");
                    UmbracoContentBuilderClass businessCentersModel = new UmbracoContentBuilderClass();
                    model.UmbracoBusinessCenters = businessCentersModel.PopulateBusinessCentersModel(businessCenters);
    
    
    
                }
                    return PartialView("~/Views/thejourney/firstpage.cshtml", model);
    
    
            }
            catch (Exception e)
            {
                CustomLogger.Error($"ERROR: BusinessCenterListingsController.BusinessCenters (GET) {e}");
                throw;
            }
    

    Partial:

    @inherits UmbracoViewPage<officefreedom.AppCode.ViewModels.MainViewModel>
    <div class="upper-nav-container col-xs-12 col-md-12">
    @Html.Partial("~/Views/Partials/_Navigation.cshtml", Model.RawContent)
    

  • Marc Goodson 2155 posts 14406 karma points MVP 9x c-trib
    Mar 14, 2020 @ 18:00
    Marc Goodson
    0

    Hi Sam

    Hmm, when you are using 'RouteHijacking' you create an MVC Controller that inherits from the special base Umbraco class: RenderMvcController following a convention that the name of the controller matches the alias of the Document Type of the page you are hijacking the request of, when you take this approach, you handle the building of a custom View Model for the page to use, and this is where your custom ViewModel should inherit from ContentModel... but your controller would return 'CurrentTemplate(yourCustomModel)' and not a Partial View.

    https://our.umbraco.com/Documentation/Reference/Routing/custom-controllers

    Within the page template you could render a further Partial View, and choose what model to send to it, eg this could be your custom ViewModel or be aware the ContentModel you are inheriting from has one property called Content which is of type IPublishedContent... so you could pass this to your Partial if that's what you need eg

    Html.Partial("navigationpartial", Model.Content)
    

    But there is another type of base controller in Umbraco called a SurfaceController, and this can be used to render PartialViews using a Child Action within another template, or for handling Form Post submissions, so I'm wondering if that somehow the two approaches are mixed up?

    https://our.umbraco.com/Documentation/Reference/Routing/surface-controllers

    and I'm unsure from your example what you are trying to achieve, eg are you trying to hijacking custom routing requests to a certain document type, or render a Partial View within another template using a SurfaceController.

    Does that help?

    regards

    Marc

  • Sam 23 posts 115 karma points
    Mar 17, 2020 @ 09:12
    Sam
    0

    Hi Marc,

    Thanks for the reply, i managed to get partials working with IPublished Content although i cannot access my custom view model (MainViewModel) and access Umbraco IPublishedContent in the same view

    particularly i have a custom search bar that needs MainViewModel and Its in the Nav which is using .Root() from IpublishedContent

    However if i use MainViewModel (Which is inheriting from ContentModel) .Root() complains model doesnt contain IPublishedContent

    Is my Custom ViewModel wrong maybe?

    public class MainViewModel : ContentModel
    {
        public MainViewModel(IPublishedContent content) : base(content)
        {
            SiteSettingsView = new SiteSettingsViewModel();
            BusinessCentersData = new List<BusinessCenterDataViewModel>();
            BusinessCenterData = new BusinessCenterDataViewModel();
            Locations = new List<LocationViewModel>();
            Location = new LocationViewModel();
            //UmbracoBusinessCenters = new UmbracoBusinessCentersViewModel();
            //UmbracoContentData = new UmbracoContentViewModel(content);
        }
    
    
        //Custom ViewModels
        public SiteSettingsViewModel SiteSettingsView { get; set; }
        //public UmbracoBusinessCentersViewModel UmbracoBusinessCenters { get; set; }
        public List<BusinessCenterDataViewModel> BusinessCentersData { get; set; }
        public List<LocationViewModel> Locations { get; set; }
        public LocationViewModel Location { get; set; }
        public string totalBCCount { get; set; }
        public string priceListing { get; set; }
        public string facilitiesListing { get; set; }
        public string officeTypeListing { get; set; }
        public BusinessCenterDataViewModel BusinessCenterData { get; set; }
        ////public UmbracoContentViewModel UmbracoContentData { get; set; }
        //public string siteName { get; set; }
        //public dynamic RootNode { get; set; }
    
    }
    

    Or maybe my Controller is wrong like you said about SurfaceController not MVCcontroller?

     public class BusinessCentersController : Umbraco.Web.Mvc.RenderMvcController
    {
        private static readonly ILog CustomLogger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private readonly IUmbracoContextFactory _context;
        public BusinessCentersController(IUmbracoContextFactory context)
        {
            _context = context;
        }
        // GET: BusinessCenters
        public ActionResult BusinessCenters(ContentModel contentModel, string searchterm)
        {
            try
            {
                var model = new MainViewModel(contentModel.Content);
    
                BusinessCenter pbcm = new BusinessCenter();
    
                model.BusinessCentersData = pbcm.PopulateBusinessCentersModel(bcjsonResult);
                model.Locations = lm.PopulateLocationsModel(allLocjsonResult);
                model.totalBCCount = totalBCs;
                model.priceListing = prices;
                model.facilitiesListing = facilities;
                model.officeTypeListing = officeTypes;
    
    
                string s = "";
                return base.Index(model);
            }
            catch (Exception e)
            {
                CustomLogger.Error($"ERROR: BusinessCentersController.BusinessCenters (GET) {e}");
                throw;
            }
        }
    
    }
    

    Many thanks, Sam

Please Sign in or register to post replies

Write your reply to:

Draft