Im struggling with getting this working the way i need.
I create a DocumentType called CustomerHome
This creates a CustomerHome Template
Create a new template called Customer.
Adjust the permissions on CustomerHome to allow the template Customer
Create an Umbraco node under content called Customers assigning the CustomerHome template and CustomerHome Document type.
Under this node create another page called Customer and assign the Customer template to it.
Create 2 new Controllers and Models for each page called CustomersController and CustomerController (notice the plural)
When i visit localhost:12/Customers, it loads my customers from my database which is using RenderMvcController (Can post the code if anyone likes).
When i visit localhost:12/Customers/customer the default template content is displayed.
When i visit localhost:12/Customers/customer/1 (Note the parameter 1) it throws an error
"Object reference not set to an instance of an object."
Highlighting the model is empty
My code on the Customer controller is
public class CustomerController : RenderMvcController
{
public CustomerController()
{
}
public new ActionResult Index(ContentModel model)
{
var vm = new CustomerContentModel(model.Content);
return View(vm);
}
}
I then read around and some suggest adding a route. I add a route and (this is where i think ive done something wrong)
public class RoutingComponent : IComponent
{
public void Initialize()
{
RouteTable.Routes.MapRoute("customers/customer/{0}", "customers/customer/{0}", new { controller = "Customer", action = "Index", id = UrlParameter.Optional });
}
public void Terminate()
{
//throw new NotImplementedException();
}
}
What i would like to happen is if they arrive at
localhost:12/Customers/customer the default empty template is displayed to say no customer found as no parameter has been passed in.
When i visit localhost:12/Customers/customer/1 I would like it to load up a customer from my database (which i can do) but i dont seem to be able to get past the error when passing in a customer ID?
I think you are caught between two methodologies...
I think you could change the ActionResult of your CustomerController to accept a parameter of customerId
eg
public ActionResult Index(ContentModel model, string customerId = "")
{
var vm = new CustomerContentModel(model.Content);
return View(vm);
}
and you wouldn't need any custom routing, because /customers/customer would map to your published content in Umbraco and having ?customerId=1
would automatically bind to your customerId parameter....
The other approach would be to use 'MapUmbracoRoute' to create a routing pattern such as /customers/customer/1 to map to a controller that imherits from RenderMvcController, and you associate an IPublishedContent context item to associate with the route by implementing a VirtualNodeRouteHandler...
There is a reasonable example or wiring this up here:
Thanks Marc, I'll try out your first solution but I'm pretty certain I tried that and got an no constructorless parameter error message or similar (for the model if I recall correctly) but will try again. Please note the Umbraco page (customer) is empty there are no properties other than title.
As for the second solution, I did read that article but I couldn't find any reference on what the class would look like for the ProductsRouteHandler class. Is there an example I could look at?
Just to ensure i have this correctly configured. I have one Doc type and two templates.
I am using the same doctype for both customers and customer but each one has a different template. Is this the correct approach? Or should i have separate doc types for each (Even though the Doctype is likely to be empty)?
Edit: I created a new separate doctype and all seems to work. So i assume you need a new doctype for all new templates? Just now trying to understand when a new DT is needed and when i can re-use an existing? Cheers
If you aren't mapping a custom route (eg the VirtualNodeRouteHandler stuff and MapUmbracoRoute)
Then for each 'DocType' you can hijack the request to it by convention by having the Controller match the name of the DocType
So what I missed in your original explanation (apologies) is that you had a controller called
CustomerController
but a doc type called CustomerHome
So you would have needed a
CustomerHomeController to 'hijack' requests to that type of page by the convention
Now you've created a Customer DocType, your existing named controller has a match!
Now by default a hijacked request will hit the Action called Index in your named controller, and return the 'Current Template' selected in Umbraco for the page.
But if a Doctype does have two templates, then you can still hijack the request for the other template in your hijacked controller by creating an ActionResult that has the same name as the template....
... so 'you could' have had
public class CustomerHomeController : RenderMvcController
{
public CustomerHomeController()
{
}
public ActionResult CustomerHome(ContentModel model) {
return CurrentTemplate(model);
}
public ActionResult Customer(ContentModel model, string customerId) {
//create custom ViewModel that inherits from ContentModel, with properties for the customer
var vm = GetCustomerViewModel(model, customerId);
return CurrentTemplate(model):
}
If you had wanted to stick with One Document Type and Two Templates, and handle each request differently!
Routing not working in Umbraco 8 (maybe)??
Im struggling with getting this working the way i need.
When i visit
localhost:12/Customers
, it loads my customers from my database which is usingRenderMvcController
(Can post the code if anyone likes).When i visit
localhost:12/Customers/customer
the default template content is displayed.When i visit
localhost:12/Customers/customer/1
(Note the parameter 1) it throws an error"Object reference not set to an instance of an object."
Highlighting the model is empty
My code on the Customer controller is
I then read around and some suggest adding a route. I add a route and (this is where i think ive done something wrong)
What i would like to happen is if they arrive at
localhost:12/Customers/customer
the default empty template is displayed to say no customer found as no parameter has been passed in.When i visit
localhost:12/Customers/customer/1
I would like it to load up a customer from my database (which i can do) but i dont seem to be able to get past the error when passing in a customer ID?Hi Linx
I think you are caught between two methodologies...
I think you could change the ActionResult of your CustomerController to accept a parameter of customerId
eg
and you wouldn't need any custom routing, because /customers/customer would map to your published content in Umbraco and having ?customerId=1
would automatically bind to your customerId parameter....
The other approach would be to use 'MapUmbracoRoute' to create a routing pattern such as /customers/customer/1 to map to a controller that imherits from RenderMvcController, and you associate an IPublishedContent context item to associate with the route by implementing a VirtualNodeRouteHandler...
There is a reasonable example or wiring this up here:
https://our.umbraco.com/Documentation/Reference/Routing/Custom-Routes/index-v8
regards
Marc
Thanks Marc, I'll try out your first solution but I'm pretty certain I tried that and got an no constructorless parameter error message or similar (for the model if I recall correctly) but will try again. Please note the Umbraco page (customer) is empty there are no properties other than title.
As for the second solution, I did read that article but I couldn't find any reference on what the class would look like for the ProductsRouteHandler class. Is there an example I could look at?
Thanks
Hi Linx
There is an example of a Virtual Node Route Handler in the core..
https://github.com/umbraco/Umbraco-CMS/blob/4be1c3b4c4f26bd0925a3164d32f554b679045da/src/Umbraco.Web/Mvc/UmbracoVirtualNodeByIdRouteHandler.cs
In fact you could use this to try out the MapUmbracoRoute...
It takes in the Umbraco Id of the content item that you want to use as your IPublishedContent context for your route.
where 1105 is the id of your placeholding customer page...
Regards
Marc
Thanks will look into that.
Just to ensure i have this correctly configured. I have one Doc type and two templates.
I am using the same doctype for both customers and customer but each one has a different template. Is this the correct approach? Or should i have separate doc types for each (Even though the Doctype is likely to be empty)?
Edit: I created a new separate doctype and all seems to work. So i assume you need a new doctype for all new templates? Just now trying to understand when a new DT is needed and when i can re-use an existing? Cheers
Hi Linx
It's all about the convention.
If you aren't mapping a custom route (eg the VirtualNodeRouteHandler stuff and MapUmbracoRoute)
Then for each 'DocType' you can hijack the request to it by convention by having the Controller match the name of the DocType
So what I missed in your original explanation (apologies) is that you had a controller called
CustomerController
but a doc type called CustomerHome
So you would have needed a
CustomerHomeController to 'hijack' requests to that type of page by the convention
Now you've created a Customer DocType, your existing named controller has a match!
Now by default a hijacked request will hit the Action called Index in your named controller, and return the 'Current Template' selected in Umbraco for the page.
But if a Doctype does have two templates, then you can still hijack the request for the other template in your hijacked controller by creating an ActionResult that has the same name as the template....
... so 'you could' have had
If you had wanted to stick with One Document Type and Two Templates, and handle each request differently!
Not sure if I've made that any clearer :-P!!!
regards
marc
is working on a reply...