Multiple types were found that match the controller named 'Home' - asp.net-mvc-2

I've just started using dotnetopenauth for my user registration. It's great, and is working perfectly.
The problem is now I'm getting an error when I try to go to /Home/ which says:
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Home' has found the following matching controllers:
OpenIdRelyingPartyMvc.Controllers.HomeController
YourApp.Controllers.HomeController
The problem is, I have no idea where OpenIdRelyingPartyMvc.Controllers.Homecontroller is coming from. I can't find ANY instance of "OpenIdRelyingPartyMvc" anywhere in my app, save 2 places, both of which occur in the UsersController:
OpenIdRelyingParty openid = new OpenIdRelyingParty();
I've tried deleting the DLL and rebuilding the app - no change. I can't figure out where this other controller would be.
Any ideas?

I had the same error message after changing the name and default namespace of the project.
Finally the solution was to manually delete all the files from debug -folder ("Clean Solution"-function of VS didn't help in this case).

My guess is that you copied the code from the samples into your codebase or you are referencing the DLL from the DotNetOpenAuth sample project. Note, OpenIdRelyingPartyMvc is the namespace of the MVC example.
So my suggestion is to first remove all instances of the DotNetOpenAuth library by starting from the project references.

use this in route.config file
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "ProjectName.Controllers" }
);
Note: Project Name which you had given while creating the project

Related

How can I create and update pages dynamically in Sulu CMS?

I have the following situation:
A database stores information about houses (address, number of rooms, date built, last selling price, etc.)
This database is being manipulated through an app (let's call that app the "backend house app") that cannot be directly integrated in a Sulu-driven app. I can access the stored data through an API that gives me JSON-representations of House-objects. I can also have the app launch some sort of call to a Sulu-driven app when a house is created, updated or deleted.
The Sulu-driven app (let's call that the "frontend house app") with templates for "house", "room", etc., is connected to a different database on a different server. This Sulu-driven app's website-environment shows house-pages with room-pages where some content is pre-filled through a connection to the "backend house app". Other content only exists on the database of the "frontend house app", like user comments, appraisals of interior design, etc., according to configured aspects of the Sulu-templates.
What I want to achieve, is a way to automate the creation, updating and deletion of "frontend house app"-pages based on activity in the "backend house app".
For instance, when a new house is added in the "backend house app", I want it to notify the "frontend house app" so that the "frontend house app" will automatically create the entire node-tree for the newly added house. Meaning: a "house"-page with the required data filled in, "room"-pages for each room, etc., so that the content manager of the "frontend house app" can see the entire tree of the newly added house in the workspace and can start manipulating content in the already available templates. In addition to automatically creating these pages, I also want to pre-set the rights to update and create, since the content manager of the "frontend house app" must not be able to create new rooms or change the name of the house, for instance.
I did not manage to get it working, I'll just add what I already done to show where I got stuck.
I started out with the following code, in a controller that extends Sulu's own WebsiteController:
$documentManager = $this->get('sulu_document_manager.document_manager');
$nodeManager = $this->get('sulu_document_manager.node_manager');
$parentHousesDocument = $documentManager->find('/cmf/immo/routes/nl/huizen', 'nl');
$newHouseDocument = $documentManager->create('page');
// The backendApi just gives a House object with data from the backend
// In this case we get an existing House with id 1
$house = $backendApi->getHouseWithId(1);
$newHouseDocument->setTitle($house->getName()); // For instance 'Smurfhouse'
$newHouseDocument->setLocale('nl'); // Nl is the only locale we have
$newHouseDocument->setParent($parentHouseDocument); // A default page where all the houses are listed
$newHouseDocument->setStructureType('house'); // Since we have a house.xml template
// I need to grab the structure to fill it with values from the House object
$structure = $newHouseDocument->getStructure();
$structure->bind([
'title' => $house->getName(),
'houseId' => $house->getId(),
]);
$newHouseDocument->setWorkflowStage(WorkflowStage::PUBLISHED); // You would expect this to automatically publish the document, but apparently it doesn't... I took it from a test I reverse-engineered in trying to create a page, I have no clue what it is supposed to change.
$nodeManager->createPath('/cmf/immo/routes/nl/huizen/' . $house->getId());
$documentManager->persist(
$newHouseDocument,
'nl',
[
'path' => '/cmf/immo/contents/huizen/' . Slugifier::slugify($house->getName()), // Assume for argument's sake that the Slugifier just slugifies the name...
'auto_create' => true, // Took this value from a test that creates pages, don't know whether it is necessary
'load_ghost_content' => false, // Idem
]
);
$documentManager->flush();
Now, when I fire the controller action, I first get the exception
Property "url" in structure "house" is required but no value was given.
I tried to fix this by just manually binding the property 'url' with value '/huizen/' . $house->getId() to $structure, at the point where I bind the other values. But this doesn't fix it, as apparently the url value is overwritten somewhere in the persist event chain, and I haven't yet found where.
However, I can, just for testing purposes, manually override the url in the StructureSubscriber that handles the mapping for this particular persist event. If I do this, something gets created in the Sulu-app-database - hurray!
My phpcr_nodes table lists two extra records, one for the RouteDocument referring to /cmf/immo/routes/nl/huizen/1, and one for the PageDocument referring to /cmf/immo/contents/huizen/smurfhouse. Both have the workspace_name column filled with the value default_live. However, as long as there are not also records that are complete duplicates of these two records except with the value default in the workspace_name column, the pages will not appear in the Sulu admin CMS environment. Needless to say, they will also not appear on the public website proper.
Furthermore, when I let the DocumentManager in my controller action try to ->find my newly created document, I get a document of the class UnknownDocument. Hence, I cannot have the DocumentManager go ->publish on it; an Exception ensues. If I visit the pages in the Sulu admin environment, they are hence unpublished; once I publish them there, they can be found by the DocumentManager in the controller action - even if I later unpublish them. They are no longer UnknownDocument, for some reason. However, even if they can be found, I cannot have the DocumentManager go ->unpublish nor ->publish - that just has NO effect on the actual documents.
I was hoping there would be a Sulu cookbook-recipe or another piece of documentation that extensively describes how to create fully published pages dynamically, thus without going through the 'manual labor' of the actual CMS environment, but so far I haven't found one... All help is much appreciated :)
PS: For the purposes of being complete: we're running Sulu on a Windows server environment on PHP 7.1; dbase is PostgreSQL, Sulu being a local forked version of release tag 1.4.7 because I had to make some changes to the way Sulu handles uploaded files to get it to work on a Windows environment.
EDIT: a partial solution for making a new house page if none exists already (not explicitly using the AdminKernel, but should of course be run in a context where the AdminKernel is active):
public function getOrCreateHuisPagina(Huis $huis)
{
$parent = $this->documentManager->find('/cmf/immo/routes/nl/huizen', 'nl'); // This is indeed the route document for the "collector page" of all the houses, but this doesn't seem to give any problems (see below)
try {
$document = $this->documentManager->find('/cmf/immo/routes/nl/huizen/' . $huis->id(), 'nl'); // Here I'm checking whether the page already exists
} catch(DocumentNotFoundException $e) {
$document = $this->setupPublishedPage();
$document->setTitle($huis->naam());
$document->setStructureType('huis_detail');
$document->setResourceSegment('/huizen');
$document->setParent($parent);
$document->getStructure()->bind([
'title' => $huis->naam(), // Not sure if this is required seeing as I already set the title
'huis_id' => $huis->id(),
]);
$this->documentManager->persist(
$document,
'nl',
[
'parent_path' => '/cmf/immo/contents/huizen', // Explicit path to the content document of the parnt
]
);
}
$this->documentManager->publish($document, 'nl');
return $document;
}
First of all I think the following line does not load what you want it to load:
$parentHousesDocument = $documentManager->find('/cmf/immo/routes/nl/huizen', 'nl');
It loads the route instead of the page document, so it should look like the following:
$parentHousesDocument = $documentManager->find('/cmf/immo/contents/nl/huizen', 'nl');
Regarding your error with the URL, instead of overriding the StructureSubscriber you should simple use the setResourceSegment method of the document, which does exactly what you need :-)
And the default_live workspace is wrong, is it possible that you are running these commands on the website kernel? The thing is that the WebsiteKernel has the default_live workspace as default, and therefore writes the content in this workspace. If you run the command with the AdminKernel it should land in the default workspace, and you should be able to copy it into the default_live workspace with the publish method of the DocumentManager.
I hope that helps :-)

Spring cloud config server - how to add custom PropertySource visible in findOne() method of EnvironmentEncryptorEnvironmentRepository

My goal is to add custom PropertySource to spring-cloud-server. What I want to achieve is to get some custom properties from that custom source in spring-cloud-config-client application.
Basing on suggestions from Adding environment repository in spring-config-server I've created spring-cloud-config-server application and separate project spring-cloud-config-custom. Second one is based on spring-cloud-consul-config code. So, I've created all necessary classes like CustomPropertySource, CustomPropertySourceLocator, CustomConfigBootstrapConfiguration and so on and configured them in spring.factories.
At the end, I've added maven dependency to spring-cloud-config-custom inside my spring-cloud-config-server.
So far so good. Everything works well. When I start server I can see that my CustomPropertySource is on the list of propertySources inside EnviromentRepository bean injected to EnvironmentController.
Problem: When I send GET request to #RequestMapping("/{name}/{profiles}/{label:.*}") (in EnvironmentController), injected EnviromentRepository bean is being used to find requested property source (repository.findOne(name, profiles, label) method).
Unfortunately my property source could not be found here. Why?
I've spent a lot of time on debugging this. I've found that repository delegates findOne() method call to other repositories: MultipleJGitEnvironmentRepository which delegates it to NativeEnvironmentRepository. Inside this delegates, findOne() method doesn't use propertySources from EnviromentRepository primary injected to controller. It creates new environment repository with new list of PropertySources and new separate SpringApplication. At the end, this list does not contain my CustomPropertySource and that is why findOne() returns empty propertySources in resulting Environment object.
Am I doing something wrong?
Is CustomPropertySourceLocator (and/or ConsulPropertySourceLocator) supposed to be used (autowired/bootstrapped) in spring-cloud-config-server or spring-cloud-config-client
Can spring-cloud-config-server deliver many different kind of PropertySources at the same time, via REST interface (saying "different" I mean all Git, Consul and Zookeeper)?
What you are doing is adding a property source to the config server itself, not the configuration it serves. Adding spring-boot-starter-actuator to your config server and viewing /env reveals:
{
"profiles": [
],
"server.ports": {
"local.server.port": 8888
},
"bootstrapProperties:custom": {
"test.prop3": "CUSTOM-VALUE-3",
"test.prop2": "CUSTOM-VALUE-2",
"test.prop1": "CUSTOM-VALUE-1"
},
}
To add something that will be served by config server, you have to implement an EnvironmentRepository.
Support for a composite EnvironmentRepository was recently added.

Laravel - How to assign relative path for subfolder controller?

I'm using laravel 4.0 for my web service project. I try to assign relative path to controller subfolder but still got the error message.
This is my router looks like
Route::group(array('prefix' => 'merchant'), function()
{
Route::resource('index', 'ProductController#showIndex');
Route::resource('product', 'CategoryController#showIndex');
Route::resource('general', 'GeneralController#showIndex');
});
Current path
/app/controllers/ProductController.php
I want to be like this one
/app/controllers/merchant/ProductController.php
Thanks a lot in advance.
You need a namespace to achieve that.
In your controller folder make a directory called merchant and place your ProductController.php inside Merchant directory.
Then open your ProductController.php and use the following namespace on top of the file.
<?php namespace Merchant;
class ProductController extends /BaseController
{
After that edit your route file:
Route::get('index', 'Merchant\ProductController#showIndex');
Remove the Route::group(array('prefix' => 'merchant'), function(). Prefix used when you have a common url for more than one routes.
For example:
http:://laravel.com/xyz/products
http:://laravel.com/xyz/category
http:://laravel.com/xyz/posts
Here xyz is common in every URL. So, In this case, you can use group routing with prefix xyz
One more thing, I can see, you have used resource controller.
Route::resource('index', 'ProductController#showIndex');
Route::resource('product', 'CategoryController#showIndex');
Route::resource('general', 'GeneralController#showIndex');
Do you know that By default, for resource controller, Laravel will generate 7 routes. So, You don't need to create #showIndex function when using resource controller.
Route::resource('index', 'ProductController');
Route::resource('product', 'CategoryController');
Route::resource('general', 'GeneralController');
More about resource controller:
http://laravel.com/docs/controllers#resource-controllers

Zend Framework 2 Override an existing Service?

I am using a zf2 module called GoalioRememberMe and now I want to override its service by my customized service. Or if it is not possible, I want to override the Module.php with my config. Is it possible?
In the Application module. I wrote this line in module.config.php:
'GoalioRememberMe\Service\RememberMe' => 'Application\Service\RememberMe'
Thanks in advance!
This is exactly the reason it is recommended to name the service as the type of the object that is returned. The object GoalioRememberMe\Service\RememberMe is named goaliorememberme_rememberme_service in the service manager. You can check that here.
So the solution is simple, instead of this:
'GoalioRememberMe\Service\RememberMe' => 'Application\Service\RememberMe'
Write this
'goaliorememberme_rememberme_service' => 'Application\Service\RememberMe'
As Jurian said, the service name is goaliorememberme_rememberme_service and it has been set in the getServiceConfig() method. So I wrote this code in the Module.php file in the Application Module:
$serviceManager->
setAllowOverride(true)->
setInvokableClass('goaliorememberme_rememberme_service', 'Application\Service\CustomRememberMe')->
setAllowOverride(false);
And it replaced successfully with my customized service!
Thanks very much to Jurian for the big help!
Actually the service manager first runs a method "canonicalizeName()" which "normalizes" the names as follows:
All _ / \ and - are stripped out
The key is made lowercase
Thus both "GoalioRememberMe\Service\RememberMe" and "goaliorememberme_rememberme_service" become "goalioremembermeremembermeservice" (i.e. they're both the same), thus the error message.
The quickest way to override an existing service is to create a *local.php or *global.php file in the /config/autoload folder. (That folder is identified in config/application.config.php.) Any override files in this folder are process after modules are loaded. If you have duplicate service manager keys, the last one wins.

Enforce Hyphens in .NET MVC 4.0 URL Structure

I'm looking specifically for a way to automatically hyphenate CamelCase actions and views. That is, I'm hoping I don't have to actually rename my views or add decorators to every ActionResult in the site.
So far, I've been using routes.MapRouteLowercase, as shown here. That works pretty well for the lowercase aspect of URL structure, but not hyphens. So I recently started playing with Canonicalize (install via NuGet), but it also doesn't have anything for hyphens yet.
I was trying...
routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();
My regular expression definitely works the way I want it to as far as restructuring the URL properly, but those URLs aren't identified, of course. The file is still ChangePassword.cshtml, for example, so /account/change-password isn't going to point to that.
BTW, I'm still a bit rusty with .NET MVC. I haven't used it for a couple years and not since v2.0.
This might be a tad bit messy, but if you created a custom HttpHandler and RouteHandler then that should prevent you from having to rename all of your views and actions. Your handler could strip the hyphen from the requested action, which would change "change-password" to changepassword, rendering the ChangePassword action.
The code is shortened for brevity, but the important bits are there.
public void ProcessRequest(HttpContext context)
{
string controllerId = this.requestContext.RouteData.GetRequiredString("controller");
string view = this.requestContext.RouteData.GetRequiredString("action");
view = view.Replace("-", "");
this.requestContext.RouteData.Values["action"] = view;
IController controller = null;
IControllerFactory factory = null;
try
{
factory = ControllerBuilder.Current.GetControllerFactory();
controller = factory.CreateController(this.requestContext, controllerId);
if (controller != null)
{
controller.Execute(this.requestContext);
}
}
finally
{
factory.ReleaseController(controller);
}
}
I don't know if I implemented it the best way or not, that's just more or less taken from the first sample I came across. I tested the code myself so this does render the correct action/view and should do the trick.
I've developed an open source NuGet library for this problem which implicitly converts EveryMvc/Url to every-mvc/url.
Uppercase urls are problematic because cookie paths are case-sensitive, most of the internet is actually case-sensitive while Microsoft technologies treats urls as case-insensitive. (More on my blog post)
NuGet Package: https://www.nuget.org/packages/LowercaseDashedRoute/
To install it, simply open the NuGet window in the Visual Studio by right clicking the Project and selecting NuGet Package Manager, and on the "Online" tab type "Lowercase Dashed Route", and it should pop up.
Alternatively, you can run this code in the Package Manager Console:
Install-Package LowercaseDashedRoute
After that you should open App_Start/RouteConfig.cs and comment out existing route.MapRoute(...) call and add this instead:
routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
new DashedRouteHandler()
)
);
That's it. All the urls are lowercase, dashed, and converted implicitly without you doing anything more.
Open Source Project Url: https://github.com/AtaS/lowercase-dashed-route
Have you tried working with the URL Rewrite package? I think it pretty much what you are looking for.
http://www.iis.net/download/urlrewrite
Hanselman has a great example herE:
http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx
Also, why don't you download something like ReSharper or CodeRush, and use it to refactor the Action and Route names? It's REALLY easy, and very safe.
It would time well spent, and much less time overall to fix your routing/action naming conventions with an hour of refactoring than all the hours you've already spent trying to alter the routing conventions to your needs.
Just a thought.
I tried the solution in the accepted answer above: Using the Canonicalize Pattern url strategy, and then also adding a custom IRouteHandler which then returns a custom IHttpHandler. It mostly worked. Here's one caveat I found:
With the typical {controller}/{action}/{id} default route, a controller named CatalogController, and an action method inside it as follows:
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
I noticed that requests to "/catalog/quick-select/1234" worked perfectly, but requests to /catalog/quick-select?id=1234 were 500'ing because once the action method was called as a result of controller.Execute(), the id parameter was null inside of the action method.
I do not know exactly why this is, but the behavior was as if MVC was not looking at the query string for values during model binding. So something about the ProcessRequest implementation in the accepted answer was screwing up the normal model binding process, or at least the query string value provider.
This is a deal breaker, so I took a look at default MVC IHttpHandler (yay open source!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
I will not pretend that I grok'ed it in its entirety, but clearly, it's doing ALOT more in its implementation of ProcessRequest than what is going on in the accepted answer.
So, if all we really need to do is strip dashes from our incoming route data so that MVC can find our controllers/actions, why do we need to implement a whole stinking IHttpHandler? We don't! Simply rip out the dashes in the GetHttpHandler method of DashedRouteHandler and pass the requestContext along to the out of the box MvcHandler so it can do its 252 lines of magic, and your route handler doesn't have to return a second rate IHttpHandler.
tl:dr; - Here's what I did:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}