I was trying to create custom pages on my broadleaf e-commerce admin side. I followed this tutorial. But when i try to access the page i get this strange error. . Here's code of my controller:
package com.community.admin.controller;
import org.broadleafcommerce.openadmin.web.controller.AdminAbstractController;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#Controller
#RequestMapping("/" + ThemeController.SECTION_KEY)
#Secured("PERMISSION_OTHER_DEFAULT")
public class ThemeController extends AdminAbstractController {
protected static final String SECTION_KEY = "test";
#RequestMapping(value = "", method = RequestMethod.GET)
public String test(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
// This is expected by the modules/emptyContainer template, this is a custom template that gets included into the body
model.addAttribute("customView", "views/test");
// ensure navigation gets set up correctly
setModelAttributes(model, SECTION_KEY);
// gets the scaffolding set up to display the template from the customView attribute above
return "modules/emptyContainer";
}
}
Also as there's no Web-INF Folder as stated in tutorial so i added my html file in Resources > open_admin_styles > templates > views folder, where other html pages were present. Any help will be appreciated thanks
P.S: I get the AccessDeniedException. I executed these following queries for permissions:
INSERT INTO `blc_admin_module` (`ADMIN_MODULE_ID`, `DISPLAY_ORDER`, `ICON`, `MODULE_KEY`, `NAME`) VALUES (1, 7, 'icon-barcode', 'MyCustomModule', 'My Custom Module');
INSERT INTO `blc_admin_section` (`ADMIN_SECTION_ID`, `DISPLAY_ORDER`, `NAME`, `SECTION_KEY`, `URL`, `ADMIN_MODULE_ID`) VALUES (1, 1000, 'My Custom Section', 'MyCustomSection', '/test', 1);
INSERT INTO `blc_admin_sec_perm_xref` (`ADMIN_SECTION_ID`, `ADMIN_PERMISSION_ID`) VALUES (1, -1);
EDIT
Removing Security Annotation can solve the problem, regardless of the fact that i added all permissions in db as stated in documentation.
Spring Framework Security use "ROLE_" prefix, so you can't use #Secured("PERMISSION_OTHER_DEFAULT") because RoleVoter won't process it.
You have to change all Broadleaf permission name, add "ROLE_" prefix to make it work.
In this case you have to change "PERMISSION_OTHER_DEFAULT" in database to "ROLE_PERMISSION_OTHER_DEFAULT" and use in controller as:
#Controller
#RequestMapping("/" + ThemeController.SECTION_KEY)
#Secured("ROLE_PERMISSION_OTHER_DEFAULT")
public class ThemeController extends AdminAbstractController {
//something
}
Do the same with other permissions.
Here are some information: https://docs.spring.io/spring-security/site/docs/4.2.13.BUILD-SNAPSHOT/apidocs/org/springframework/security/access/vote/RoleVoter.html
The above answer resolves the security issues. But I don't find Web-INF Folder as well as Resources > open_admin_styles > templates > views folder too in admin on version 6.1.5-GA.
Then I add the test.html file on
admin > src > main > resources > community-demo-style.templates.admin
folder.
And also in MyController Class gives /test.html to model.addAtrribute() like model.addAttribute("customView", "/test.html");
It works fine for me.
MyController image
Related
I'm just getting to grips with ViewComponents in my Razor pages application.
I have a ViewComponents folder within my project that contains my ViewComponent .cs code:
public class RemoveFromCartViewComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
var result = "123";
return View(result);
}
}
I then have another folder within Pages/Shared/Components called RemoveFromCart. Within this folder I have my default.cshtml
#model string
<h2>
#Model
</h2>
Simply putting the string within a h2 tag.
In my projects Layout.cshtml file I am invoking this ViewComponent:
<div>
#await Component.InvokeAsync("RemoveFromCart")
</div>
When I start my project, the error I get is:
*InvalidOperationException: The view 'Components/RemoveFromCart/123' was not found. The following locations were searched:
/Pages/Components/RemoveFromCart/123.cshtml
/Pages/Shared/Components/RemoveFromCart/123.cshtml
/Views/Shared/Components/RemoveFromCart/123.cshtml*
This is indication my view should be called 123.cshtml which doesnt seem right. What am I doing wrong here? I should simply expect to see the text 123 appear
Thanks
By returning View("123"), you are using this overload:
public ViewViewComponentResult View (string viewName)
Returns a result which will render the partial view with name viewName.
So you are passing the view name, instead of a string value as the view’s model.
You can change that by explicitly calling the View<TModel>(TModel) overload instead:
public IViewComponentResult Invoke()
{
var result = "123";
return View<string>(result);
}
In the long run, I would suggest you to create a model class instead so that you can pass an object instead of just a string. This will avoid having this particular problem and you are also able to easily expand the model contents later on.
I'm using tapestry 5.4.1. I have a component with a module that requires prototype. I know prototype is available in the core stack. However how do I import this as a dependency.
My module:
define(["prototype"], function(container, link) {
return new Ajax.PeriodicalUpdater(container, link, {
method : 'post', frequency : 5, decay : 1
});
});
I tried adding this to the class but the path cannot be resolved
#Import(library = {"prototype.js"})
public class Update {
Tried injecting the asset and adding it to the environmental javascriptsupport but it somehow looks for it in the wrong location.
#Inject
#Path("classpath:META-INF/assets/tapestry5/prototype.js")
private Asset prototype;
and
javascriptSupport.importJavaScriptLibrary(prototype);
javascriptSupport.require("update").with(container, getLink());
I don't want to hard code the url with the generated hash.
/assets/meta/z67bxxxx/tapestry5/scriptaculous_1_9_0/prototype.js
Anything I am missing here? Any help would be appreciated.
Make sure you define correct infrastructure in your AppModule
#ApplicationDefaults
public static void contributeApplicationDefaults(MappedConfiguration<String, Object> configuration) {
configuration.add(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER, "prototype");
}
You don't have to specify dependency clearly ["prototype"].
I have created one controller inside catalog/controller/module/same_collection.php
Inside that :
class ControllerModuleSameCollection extends Controller {
//User Product History
public function index($product_id) {
echo $product_id;
}
}
I have try to call it inside another controller like this
$data['same_color'] = $this->load->controller('module/same_color' ,['product_id' => 2] );
and I try to by access it using url like this
mydomain.com/index.php?route=module/same_collection&product_id=2
but it's not working.
Please help!!!
It seems like you have not created your module properly. Make sure your module's setting is saved in module table . If your module's code is not there in the table then you won't get any parameter in your index() method.
Standard MVC pattern for ControllerC/ActionA when controller code just states return View() is to look for ControllerC/ActionA.cshtml. I would like make it so if such view does not exist, it looks for some default view like Shared/Default.cshtml. How can I do this?
I don't know about MVC 5, but you could create custom class from RazorViewEngine.
public class MyFallbackLocationViewEngine : RazorViewEngine
{
public MyFallbackLocationViewEngine()
{
// Keep default locations and add our own fallback view
List<string> newLocations = new List<string>(ViewLocationFormats);
newLocations.Add("~/Views/Shared/Default.cshtml");
this.ViewLocationFormats = newLocations.ToArray();
}
}
And add it to your Application_Start:
// Clear default engines and add only yours
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MyFallbackLocationViewEngine());
You could customize your ViewEngine as much as you lilke and override other methods
I want to have a plug-in system (like wordpress ) , How can I list my admin controller in layout.phtml ?
The list of modules if available in the module manager (Zend\ModuleManager\ModuleManager). You can get the module manager via the service locator. For example in your controller:
class MyController extends AbstractActionController
{
public function indexAction()
{
$manager = $this->getServiceLocator()->get('ModuleManager');
$modules = $manager->getLoadedModules();
}
}
The controllers have access to the layout (and its parameters) via the layout controller plugin.
$this->layout()->modules = $modules;
An alternative is that you create a view helper. In this view helper, you get the module manager and then return the list of modules.