MVC6 View Referencing issue due to routing - asp.net-mvc-routing

In my solution I have at the root level a Controller, Views Folder each of these have a Home Folder with an Home Controller with Index method and the view folder with an index view (default MVC setup). At the root level I have introduced an Areas folder then in here I have created another Folder for the area then folders for controllers and views. Home controller with index method and views folder with index view.
it all builds fine, but I receive the following error:
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
VisualJobs.Controllers.HomeController.Index (VisualJobs)
VisualJobs.Areas.Recruiter.Controllers.HomeController.Index
(VisualJobs) VisualJobs.Areas.Jobs.Controllers.HomeController.Index
(VisualJobs)
in my Configuration file I have:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Folder structure:
Areas -->Candidate-->Controllers
Shared
ViewModels
Views
Areas -->Recruiter-->Controllers
Shared
ViewModels
Views
Controllers
Views

It may be because you have not decorated your area controller classes with the Area attribute. Something like this.
[Area("Recruiter")]
public class MyController : Controller
{
...
}
You also need _ViewImports.cshtml and _ViewStart.cshtml in the Views folder of your area.

Related

How to retrieve view's ID with application prefix?

To retrieve prefixed ID of a control we can use view's method CreateID. However, there's no such a method in class sap.ui.core.Core. So how do I know viewID in the line
sap.ui.getCore().byId(viewID)
The Core is common to all the applications you are loading into your HTML document. An specific view of an specific application can have a different ID depending on how many different views you already loaded. The CreateID method makes sense to create an ID prefixed by the relevant View ID, but the view IDs are not prefixed but just autogenerated.
So, to get the ID of the current view, just do this.getView() in its controller and get the ID from the returned object.
If you want to know the ID of a different view to the one you are visualizing/loading, then you need to navigate through all the views in your DOM and design your own way to identify it.
However I don't recommend you to modify a View from a controller of another view. Each View should be modified by the logic in its controller only, and no by other controllers, to maintain the principles of the MVC architecture
EDIT:
How to access your component:
If you bind the context of your app execution with the Push.js script, then use this.getOwnerComponent().
If you don't, then you need to access your Component from the core with sap.ui.getCore().getComponent('componentID')
Now the problem is how to know the componentID. Well, I see two options here, give an ID to your component, or map the autogenerated component IDs in a Core variable.
How to retrieve a specific Component:
Option 1: Define a Component ID
Whenever you initialize it, usually in the index.html file, you can do it like this:
<script>
sap.ui.getCore().attachInit(function() {
sap.ui.component({
id: "myComponentID",
async: true,
name: "myNamespace", // The namespace you defined in the bootstrap tag and points to the folder where the Component.js file is stored
manifestFirst: true
}).then(function(oNewComponent){
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
component: oNewComponent,
height : "100%"
})
}).placeAt("content");
})
});
</script>
With this option you can retrieve your Component as sap.ui.getCore().getComponent('myComponentID') and of course whatever model registered in it with sap.ui.getCore().getComponent('myComponentID').getModel('modelName')
Option 2: Map the autogenerated components IDs with your identifiers in a Core variable
I don't like to change the Components ID, and there are some times when you have no chance to do it. So in the past I did it like in the following snippet (probably not the best/elegant solution out there, but it works good)
Component.js
/**
* The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
* #public
* #override
*/
init: function() {
//Map Component ID in a Core variable
if(!sap.ui.getCore()._data_oLoadedComponents){
sap.ui.getCore()._data_oLoadedComponents = {};
}
sap.ui.getCore()._data_oLoadedComponents.myCustomComponentId = this.getId(); // myCustomComponentId is the ID you want to use for this specific app
// END: Map Component ID in a Core Variable
// call the base component's init function
UIComponent.prototype.init.apply(this, arguments);
// set the device model
this.setModel(models.createDeviceModel(), "device");
}
So now you can access any of your components getting the autogenerated ID from your mapping variable like this:
sap.ui.getCore().getComponent(sap.ui.getCore()._data_oLoadedComponents.myCustomComponentId)
and also access the model like this:
sap.ui.getCore().getComponent(sap.ui.getCore()._data_oLoadedComponents.myCustomComponentId).getModel('modelName')

Zend 3 - Change template basepath

I am just starting to migrate some of my applications from Zend#1 to Zend#3. All is working fine, but regarding the views I've some trouble understanding the underlying concept.
As the tutorials suggest my project layout is like this:
module
Application
view
application
index
main.phtml
foo.phtml
baz
index.phtml
I'm wondering why you need to dublicate the "application" folder inside the view directory - you are already in the directory hirachy of the module. Is there a way to change the search path for the default template resolver so that the module name is omited? Just relying on the viewManager's "template_path_stack" is not working. Do I really need to write a custom resolver here?
Thanks a lot!
PS. Nope, I do not want to use custom template maps here ;-) I want to understand and use the default revolver without template maps, if possible.
"Application" is the name of a module in your overall 'application.' At the start, "Application" is the only module, but it is common to add other modules: you might have a module for "Clients" and another module for "Vendors." The hierarchy of the view folders follows the same hierarchy as ModuleName:ControllerName:ActionName, and ZF needs to use the module name in the view folders hierarchy in case you happen to have identical controller and action name pairs in two or more modules. It is likely that a "Clients" module and a "Vendors" module will both have an "index" action. It is less likely that the two would have identical controller names but it's not completely out of the question. If you had a controller named "Contacts" in both a "Clients" module and a "Vendors" module, "contacts/index" isn't enough information to tell ZF which view to use. It needs the module name in the folder hierarchy to distinguish between "clients/contacts/index" and "vendors/contacts/index".
UPDATE
Something to wrap your head around is that ZF3 takes things like router definitions, view folders and who knows what else from all of your different modules and aggregates them into a single structure. In other words,
module
Application
view
application
add
add.phtml
delete
delete.phtml
edit
edit.phtml
index
index.phtml
module
Clients
view
clients
add-client
add.phtml
delete-client
delete.phtml
edit-client
edit.phtml
client-index
index.phtml
module
Vendors
view
vendors
add-vendor
add.phtml
delete-vendor
delete.phtml
edit-vendor
edit.phtml
vendor-index
index.phtml
gets recognized somewhat like this:
module
....
view
application
add
add.phtml
delete
delete.phtml
edit
edit.phtml
index
index.phtml
clients
add-client
add.phtml
delete-client
delete.phtml
edit-client
edit.phtml
client-index
index.phtml
vendors
add-vendor
add.phtml
delete-vendor
delete.phtml
edit-vendor
edit.phtml
vendor-index
index.phtml
and you could probably put all of your view files into a single module if you wanted to.
Perhaps this helps explain why a folder with the module name is included beneath the "view" folder. The folder with the module name that is above the "view" folder has a storage function. The folders with module names below the "view" folder serve as a means of referencing which modules the view files are associated with in the aggregated definition.
Found one possible solution!
In your module's config add this one to the view_manager::
'controller_map' => [
'Dashboard\Controller\DashboardController' => 'Dashboard'
],
Instead of looking for a template called "Dashboard/view/dashboard/[controller]/[action].phtml" the framework will now look for "Dashboard/view/[controller]/[action].phtml". Basically you are telling Zend to use some kind of shorthand here and strip the array's value from the template resolution (have a look at InjectTemplateListener::mapController())
Anyways... a better solution and explanation is welcome!

sails js layout view change folder

My project has more than one layout, I want to make a folder to contain these layouts and pull them out of the view folder, but when I do this, the layout does not load when I run the application.
How could I solve this?
Tx in advance.
To solve this you have two options, depending on whether you are using routes or the controller to serve your views.
Firstly, let's say you have a folder "mylayouts" in your views folder and this folder contains numerous layouts eg. "layout_home.ejs", "layout_admin.ejs" etc.
To use these layouts for a specific view, you can:
A. Set the layout using locals in the config/routes.js file, be sure to include both the folder name and layout filename. eg.
'/': {
view: 'homepage',
locals: {
layout: '/mylayouts/layout_home.ejs'
}
}
B. Set the layout in the response from the controller, again insuring to include both the folder name and layout filename. eg.
/**
* AdminController
*
* #description :: Server-side logic for managing admins
* #help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
module.exports = {
index : function(req, res){
res.view({
layout : '/mylayouts/layout_admin.ejs'
})
}
};

Zend Framework + Tricky controller name and module name conflict

We have a Zend application that has these following modules:
Users
Shop
etc...
Front - A content management module
While the Front module has the following controllers:
UsersController
ShopController
AuthController
etc...
In the middle of our development cycle we decided to set the default module for the Zend application to the Front module, but inadvertently broke our links, as http://domain.com/front/users/list are now generated as http://domain.com/users/list, which is now pointing to the wrong action.
We are generating links using the URL view helper, (i.e. $this->url(array('module' => 'front', 'controller' => 'users', 'action' => 'list'));), but the 'front' URI segment is omitted since switching the default module to the Front module.
I totally understand why this is so, but we are avoiding renaming all controllers under the Front module to avoid conflicts.
My question is, is there is a way to instruct the URL view helper to always include the 'front' module URI segment even if it is already set as the default one?
My question is, is there is a way to instruct the URL view helper to
always include the 'front' module URI segment even if it is already
set as the default one?
You can create your own url view helper with same name and override default url view helper add it to Zend_View object in your bootstrap.
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
if (null === $viewRenderer->view)
{
$viewRenderer->initView();
}
$view = $viewRenderer->view;
$view->addHelperPath('/path/to/some/helpers', 'My_View_Helper');
Now create class My_View_Helper_Url let it extend Zend_View_Helper_Url override url method.
Here is reference form ZF doc about this procedure
In fact, you can "stack" paths using the addHelperPath() method. As
you add paths to the stack, Zend_View will look at the
most-recently-added path for the requested helper class. This allows
you to add to (or even override) the initial distribution of helpers
with your own custom helpers.
Having said that I think http://domain.com/users/list, should have worked correctly in first place since you have specified default module to front.

Zend Framework - Extending Controllers

I'd like to have my controller - i.e. Page_IndexController - extend a base controller.
For example;
class Page_IndexController extends Content_IndexController {
}
However, it seems the autoloader doesn't pick up the fact it's a controller class at any point - I get the error Fatal error: Class 'Content_IndexController' not found
First question: How do I fix this?
I can temporarily fix this by require_once'ing the generic 'content' controller, but this is hardly ideal.
The next issue is that if my Page controller has it's own view script for an action, it works no problem.
But if I'm extending a controller, and I call for example 'listAction' on the Page controller, but this action is implemented in Content_IndexController, it still looks for the list view script in the page controllers "scripts" directory.
Second question: How do I configure my controller to use its parents view script if it doesn't have its own?
If your application can find Page_IndexController you probably have a Page module. If you are not using modules in your application you have to name your controllers PageController and ContentController, not Page_IndexController, ... So the solution is to register "Content_" namespace with the autoloader.
As for the second question. You can extend the provided ViewRenderer controller action helper and override methods for finding the view script so they can look in other places if needed. You just have to pass your viewrenderer to the front controller. For passing your own ViewRenderer to the controller take a look at Advanced Usage Examples.
The auto loader can't find your controller because you haven't told it where to search. The Content_IndexController isn't in your "library" folder (I assume its inside of the Content module)
What I would suggest is creating a My_Controller_IndexBase class in your library folder that both Content_IndexController and Page_IndexController inherit.
Did a little more research on the topic of the view script. You could change up the view's script paths during init() somewhere. I'm pretty sure this would probably need to be done in a ViewRenderer - but might also work inside the controller's init/action code.
$this->view->setScriptPath(
array(
realpath(APPLICATION_PATH+'/../path/to/other/module/views'),
) + $this->view->getScriptPath());
Script paths are processed Last In First Out according to the Zend_View_Abstract
For the second question:
If you don't want to write your own ViewRenderer, you can use $this->renderScript('parent/index.phtml') to render a specific view script. You could call that in your child controllers instead of letting the views be rendered for you automatically, or if your child controllers rely on the parent controller to do the rendering of the script you can just place that in your parent controllers.
I do that mode.
Frist I register a new name who a plugin in my index.php into the public folder:
/public/index.php
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('modelo_');
Secound I create a new folder to put my controller
/library/modelo/
Third I create my controller model and put it into the folder created and rename it.
class Modelo_ModeloController extends Zend_Controller_Action
{
protected $_db = null;
protected $_menu = null;
protected $_util = null;
protected $_path = null;
... actions to my model
public function inicial(){}
}
and I extend this class im my application
class Sispromo_PedidoController extends Modelo_ModeloController
{
public function init(){}
....
}