Copied to clipboard

Flag this post as spam?

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


  • Jason 92 posts 175 karma points
    Oct 07, 2015 @ 20:35
    Jason
    0

    Route-hijacked custom document types throwing an error (Bazaar store)

    Hi Rusty,

    I'm running the Combined install with v1.10.

    The navigation is throwing an object reference not set to instance.. while trying to use my own document types. eg I have created a ProductGroup landing page (which in turn displays multiple ProductGroups).

    The offending line is:

    if (currentCustomer.IsAnonymous)
    

    My custom controller inherits the RenderMvcController. Should I be inheriting a BazaarControllerBase or similar instead (which would include an instance of a Customer)? I checked the Bazaar source and it looks like I should be, however it doesn't seem to exist in the combined install. Was there a previous way of doing it?

    cheers

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Oct 07, 2015 @ 20:43
    Rusty Swayne
    0

    @Jason

    Try inheriting from

     Merchello.Web.Mvc.MerchelloRenderMvcController
    

    so that the customer context is instantiated.

  • Jason 92 posts 175 karma points
    Oct 07, 2015 @ 21:01
    Jason
    0

    @Rusty

    Thanks. Tried inheriting from both MerchelloRenderMvcController and RenderControllerBase - still object not set error I'm afraid

     public class CategoriesLandingPageController : MerchelloRenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            var viewModel = new CategoriesLandingPage(model.Content) { };
            return View(viewModel.ThemeViewPath("CategoriesLandingPage"), viewModel);
        }
    }
    

    I feel like i'm doing something wrong in my return value

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Oct 07, 2015 @ 22:01
    Rusty Swayne
    0

    I think 1.10 is using the MasterModel rather than IPublishedContent for the Master.view ...

    Does CategoriesLandingPage inherit from MasterModel - and is the offending line in the controller or in the view?

     if (currentCustomer.IsAnonymous)
    
  • Jason 92 posts 175 karma points
    Oct 07, 2015 @ 22:09
    Jason
    0

    Yes that's correct, and the CategoriesLandingPage (model) is inheriting from MasterModel. The offending line is in the Nav view.

    public class CategoriesLandingPageController : MerchelloRenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            var viewModel = new CategoriesLandingPage(model.Content) { };
            return View(viewModel.ThemeViewPath("CategoriesLandingPage"), viewModel);
        }
    }
    

    The model isn't particular adding much as you can see

     public class CategoriesLandingPage : MasterModel
    {
        public CategoriesLandingPage(IPublishedContent content)
            : base(content)
        {
    
        }
    }
    

    and the view (part of)

    <ul class="nav navbar-nav navbar-right">
                 @if (Model.ShowAccount)
                {
                    <li class="dropdown">
                        <a class="dropdown-toggle" data-toggle="dropdown" href="#">@GetAccountDropDownName(Model.CurrentCustomer) <b class="caret"></b></a>
                        <ul class="dropdown-menu" id="swatch-menu">
                            @if (Model.CurrentCustomer.IsAnonymous)
                            {
                                <li><a href="@Model.RegistrationPage.Url">Sign Up / Login</a></li>
                            }
                            else
                            {
                                <li><a href="@Model.AccountPage.Url">Account</a></li>
                                var purchaseHistory = Model.AccountPage.Descendant("BazaarAccountHistory");
                                if (purchaseHistory != null)
                                    {
                                    <li><a href="@purchaseHistory.Url">Purchase History</a></li>     
                                    }
                                <li>@Html.ActionLink("Logout", "HandleSignOut", "MembershipOperations", new { area = "Bazaar" }, null)</li>
                            }
                        </ul>
                    </li>
                }
                <li><a href="/basket"><span class="icons fa fa-shopping-cart"></span>Basket</a></li>
                <li><a href="/checkout"><span class="icons fa fa-credit-card"></span>Checkout</a></li>
            </ul>
        </div>
    </nav>
    

    @functions
    {
    /// <summary>
    /// Returns the customer name or "Account" for the Account link based on login status
    /// </summary>
    /// <param name="currentCustomer">Mechello's <see cref="ICustomerBase"/></param>
    /// <returns>A string label for the Acccoun tab</returns>
    /// <remarks>
    /// A bit hacky here, but it does the trick.
    /// </remarks>
    private string GetAccountDropDownName(ICustomerBase currentCustomer)
    {
        if (currentCustomer.IsAnonymous) return "Account";
    
        var customer = (ICustomer)currentCustomer;
        var name = customer.FullName;
    
        if (!string.IsNullOrEmpty(name)) return name;
    
        return "Account";
    }
    

    }

  • Jason 92 posts 175 karma points
    Oct 08, 2015 @ 20:24
    Jason
    0

    @Rusty

    Looking at the Bazaar.dll (1.10), the BazaarProductGroupController calls a ViewModelFactory. I'm unsure about the line 'this.ViewModelFactory.CreateProductGroup(model). In this case, what is 'this'?

    namespace Merchello.Bazaar.Controllers
    {
      [PluginController("Bazaar")]
      public class BazaarProductGroupController : RenderControllerBase
      {
     public override ActionResult Index(RenderModel model)
    {
      ProductGroupModel productGroup = this.ViewModelFactory.CreateProductGroup(model);
      return (ActionResult) this.View(ModelExtensions.ThemeViewPath((IMasterModel) productGroup, "ProductGroup"), (object) productGroup);
    }
    }
    }
    

    The customer is injected in at ViewModelFactory

      public class ViewModelFactory : IViewModelFactory
    {
    private readonly ICustomerBase _currentCustomer;
    private readonly ICurrency _currency;
    private Lazy<BasketLineItemFactory> _basketLineItemFactory;
    private Lazy<SalePreparationSummaryFactory> _salePreparationSummaryFactory;
    
    public ViewModelFactory(UmbracoHelper umbraco, ICustomerBase currentCustomer, ICurrency currency)
    {
      Mandate.ParameterNotNull<ICustomerBase>(currentCustomer, "currentCustomer");
      Mandate.ParameterNotNull<ICurrency>(currency, "currency");
      Mandate.ParameterNotNull<UmbracoHelper>(umbraco, "umbraco");
      this._currentCustomer = currentCustomer;
      this._currency = currency;
      this.Initialize(umbraco);
    }
    
  • Jason 92 posts 175 karma points
    Oct 08, 2015 @ 20:57
    Jason
    1

    a bit hacky, but if anyone is interested I 'resolved' the issue as follows:

     public override ActionResult Index(RenderModel model)
        {
            var viewModel = new CategoriesLandingPageModel(model.Content) { };
            viewModel.CurrentCustomer = this.CurrentCustomer;
            return View(viewModel.ThemeViewPath("CategoriesLandingPage"), viewModel);
        }
    
  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Oct 08, 2015 @ 20:59
    Rusty Swayne
    1

    I think that approach is fine - it's the same thing that was done in the factory =)

  • Jason 92 posts 175 karma points
    Oct 08, 2015 @ 21:10
    Jason
    0

    Although if you wanted to do it 'correctly' then a new method would need to be created within the ViewModelFactory, returing a base model of some sort instead? Not to worry in this instance - if it was a larger application with lots of different document types then I would be more concerned!

Please Sign in or register to post replies

Write your reply to:

Draft