Piranha CMS Management Custom Controller Not Found - piranha-cms

I am having an issue with adding a custom controller to my Piranha CMS.
I have set up a new site and installed from the template and all the base functionality is working well.
I have added the menu to the manager section using the following code from the documentation:
Manager.Menu.Add(new Manager.MenuGroup()
{
InternalId = "MEProducts",
Name = "Products"
});
Manager.Menu.Where(m => m.InternalId == "MEProducts").Single().Items =
new List<Manager.MenuItem>() {
new Manager.MenuItem() {
Name = "Products",
Action = "productlist",
Controller = "products",
Permission = "ADMIN",
SelectedActions = "productlist,productedit"
},
new Manager.MenuItem() {
Name = "Product groups",
Action = "productgrouplist",
Controller = "products",
Permission = "ADMIN",
SelectedActions = "productgrouplist,productgroupedit"
}
};
This menu displays in the manager interface fine, the problem is when I click on the menu item the controller path can not be found.
The controller is class is in Areas/Manager/Controllers/ProductsController.cs and the code is below
namespace MyApp.Areas.Manager.Controllers
{
public class ProductsController : ManagerController
{
//
// GET: /Manager/Products/
public ActionResult Index()
{
return View();
}
public ActionResult ProductList()
{
return View();
}
public ActionResult ProductEdit(string id = "")
{
return View();
}
}
}
There are view files for ProductList and ProductEdit in Areas/Manager/Views/Products/
My web config contains the following line that I believe I need
<add key="manager_namespaces" value="MyApp.Areas.Manager.Controllers" />
When I click on the Products link in the manager I get
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /MyApp/manager/products/productlist
The page /MyApp/manager/page displays fine for the default configuration.
I am sure that I have missed something, or done something incorrect somewhere I'm just not sure where it is.

I've tried reproduce your issues but it works perfectly with your productscontroller in my project. I've zipped my test-project and uploaded it to my dropbox so you can download and compare it to your project:
EDIT
Removed download link as author downloaded the file
Please let me know when you've downloaded the zip-file so I can delete it.
Regards
HÃ¥kan

Related

How to block access to controller via changing Url in ASP.NET Core?

I want to access page when user clicks to button.
By changing url, such as ..../Member/Batch/Create I want my site redirect user to another page.
How can I do this via ASP.NET Core MVC 3.1?
Use:
Create Batch
See this answer and help for more details.
Do you mean we could only access the controller by using button?
If this is your requirement, you could try to check the Request.Headers["Referer"].ToString() to make sure just which url could access this controller.
Like below:
public IActionResult Privacy()
{
var re = Request.Headers["Referer"].ToString();
if (Request.Headers["Referer"].ToString() != "https://localhost:44342/home/index")
{
return View("Error");
}
else
{
return View();
}
}
Result:

Partial view not sending model in subdomain

I have a MVC4 published in a subdomain.
Since I've published, partial views are not sending model changings to controller.
This is on .cshtml:
#using (Ajax.BeginForm("_PartialEmpreendimentos", "Empreendimentos", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "Resultados",
LoadingElementId = "loader",
OnSuccess = "setBusy"
},
new { #name = "FormPrincipal" }))
{
#*<%-- Resultados --%>*#
Html.RenderAction("_PartialEmpreendimentos", Model);
}
Here I have the controller:
public ActionResult _PartialEmpreendimentos(PesquisaEmpreendimentoDto pesquisa)
{
code here...
return PartialView("_PartialEmpreendimentos", pesquisa);
}
When access the action up here, the model is empty.
Any idea what can I do?
Here is the website from example:
http://dev.centure.com.br/dev/Empreendimentos/EmpreendimentosLista/
The submit access the controller, but with a empty model
Work fine in localhost
It's in a shared host, so the route insert "/dev/" in every action link.
UPDATE
Viewing the network sending the model was sent as well, with all parameters fine. That make me think that the problem is the response, not in calling of controller.
UPDATE 2
In network I'm receiving 302 code response. This make the page redirect to get action on controller, I think.
Please help, I'm desperate!
So, I couldn't resolve it.
I just published in a absolute domain, and so it is.
It seems there no way to use a shared host and keep things working fine.

Controller not working after publish to azure website

I have created a simple web site using ASP.Net MVC 4, Internet Application. I added a controller, model and associated views for a new page. Everything works fine running locally, I can register, login and use my new page functionality. After publishing to Azure website I can successfully use the home, about, register, login all of the built in functionality. However I cannot navigate to my new content I added, it gives an error 500. Again all of this functionality does work locally. I am very new to ASP.Net MVC and could use any help I can get.
RouteConfig
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Index action of my added controller
private UsersContext uc = new UsersContext();
private UserProfile user = new UserProfile();
private Character character = new Character();
//
// GET: /Character/
public ActionResult Index()
{
user = uc.UserProfiles.Single(u => u.UserName == User.Identity.Name);
return View(uc.Characters.ToList().Where(c => c.AccountOwnerId == user.UserId));
}
Let me know if any other items would help. Oh I put this into my UsersContext instead of in a newly created DbContext.
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Character> Characters { get; set; }
EDIT: one thing i forgot to mention is that when i published, it did not add the email address field to userprofile or my entire Character table. I had to run SQL on the Azure manage portal to manually add those items.
After all the frustration of trying to understand why this wasn't working I decided to start over. I deleted the website from Azure as well as the SQL DB. I then added a new website and SQL DB then grabbed the new publish settings file. I imported that into VS and Published. It all worked with a fresh install, not sure what I botched the first time around but it is working as intended now. Thanks,

MVC 4 mapping files in directory to controller action to ensure authorized access to documents

If I have a file in a directory on my website:
~/documents/file1.pdf
How can I force requests to the following url to go through a controller:
www.mydomain.com/documents/file1.pdf
The controller would then look something like
[Authorize]
public DocumentsController : Controller
{
public FileResult Index(string fileName)
{
//Check user has permission to view file
return File(...);
}
}
I got round this by putting the documents directory in the App_Data folder so it's not accessible to the public and the using the document's ID from the database to retrieve the relevant information e.g.
/documents/21
I think I prefer this approach anyway to my initial plan because it abstracts the identity of the path and document title far more thoroughly as the controller path can be anything and doesn't have to map to a physical directory path.
This is not difficult, so long as you can make some assumptions.
First, you create your action method as you propose:
[Authorize]
public DocumentsController : Controller
{
public FileResult Index(string fileName)
{
//Check user has permission to view file
return File(...);
}
}
Next, you create a route:
routes.MapRoute(
name: "Documents",
url: "documents/{fileName}",
defaults: new { controller = "Documents", action = "Index" }
You may be required to relax the url validation requirements by adding the following to web.config (this only works in IIS7-8 though as far as I know, IIS6 would require an http module I think):
<httpRuntime relaxedUrlToFileSystemMapping="true" />

Seeding data and creating/managing roles in MVC4 - how hard can it be?

I'm about to go insane, so I'll try getting some help one more time...
I'm using Visual Studio Express 2012 for Web to create an internet project using C# + MVC4 + Razor + Entity Framework + ASP.NET 4.5.
I need to do the following: automatically create an "admin" user (who will be authorized all over the site) and then create some user roles.
I've read about SimpleMembership, roles and everything all over the web, but nothing seems to give me a straightforward method to make the whole thing work.
This is what I've done so far:
1- Created a DataContext class:
public class DataContext : DbContext
{
public DataContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
2- Created an initializer class with what I assume would get me the admin user and Admins role created:
public class DataContextDbInitializer : DropCreateDatabaseAlways<DataContext>
{
protected override void Seed(DataContext context)
{
var roles = (Webmatrix.WebData.SimpleRoleProvider)System.Web.Security.Roles.Provider;
var membership = (Webmatrix.WebData.SimpleMembershipProvider)System.Web.Security.Membership.Provider;
if (!roles.RoleExists("Admins")) {
roles.CreateRole("Admins");
}
if (membership.GetUser("admin", false) == null) {
membership.CreateUserAndAccount("admin", "123456");
}
if (!roles.GetRolesForUser("admin").Contains("Admins")) {
roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
}
}
}
(I've tried inheriting from DropCreateDatabaseIfModelChanges but that doesn't help).
3- Added two lines to the App_Start method in Global.asax:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
Database.SetInitializer<DataContext>(new DataContextDbInitializer());
I also tried using WebSecurity.InitializeDatabaseConnection in the Seed method in my DataContextDbInitializer class, but didn't work.
4- Removed the [InitializeSimpleMembership] annotation from the AccountController, so I can initialize it from the very beginning of the application life cycle (using WebSecurity.InitializeDatabaseConnection in App_Start, as I've explained in number 3). I tried adding [InitializeSimpleMembership] on top of the Index method in the HomeController and removing WebSecurity.InitializeDatabaseConnection from App_Start, but that doesn't help either.
5- In Web.config I have authentication method as Forms (default) and also left the default connection string:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-TPFinal-20130121210447;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-TPFinal-20130121210447.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
And added this inside the system.web tag:
<roleManager enabled="true" cacheRolesInCookie="true" />
6- Then, to test if everything works, I use the [Authorize(Roles = "Admins")] annotation on top of the About() method in the HomeController. If things were working as expected, this should force me to log in as admin/123456 in order to be able to see the "About" page, controlled by HomeController/About.
7- I haven't added EF migrations or anything else. All the other stuff is by default as VS2012 automatically created it.
So I run my application and click on the "About" link, and I get presented with the login form (that means that the [Authorize(Roles = "Admins")] annotation is doing what it's expected to do). I attempt to log in as admin/123456 but the log in page is reloaded over and over, every time I click on the log in button.
A few things I have noticed:
-if I add a breakpoint in the Seed method, it seems it's not getting called.
-when I use DropCreateDatabaseAlways and run the application again, I'm able to log in as admin/123456, which makes me think again that my whole DataContextDbInitializer class is not even being used, since I assume the DB should be created from scratch, which would delete the admin user.
I don't know what else to read, what else to try... I'm new to asp.net (needed I say that?) and just going nuts.
Thanks!!
Finally, I managed to make the whole thing work!
My seed method now looks like this:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
if (!Roles.RoleExists("Admins"))
{
Roles.CreateRole("Admins");
}
if (!WebSecurity.UserExists("admin"))
{
WebSecurity.CreateUserAndAccount("admin", "123456");
}
if (!Roles.GetRolesForUser("admin").Contains("Admins"))
{
Roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
}
base.Seed(context);
My App_Start in Global.asax looks like this:
Database.SetInitializer(new DataContextDbInitializer());
DataContext c = new DataContext();
c.Database.Initialize(true);
I'm not sure if this is actually doing something, but I have this inside the the system.web tag in Web.config:
<roleManager enabled="true" cacheRolesInCookie="true" />
I also removed [InitializeSimpleMembership] from AccountController, and the UsersContext class in AccountModels. I moved this bit to my own context class:
public DbSet<UserProfile> UserProfiles { get; set; }
Then, to test if everything works, I use the [Authorize(Roles = "Admins")] annotation on top of the About() method in the HomeController. If things are working as expected, this should force me to log in as admin/123456 in order to be able to see the "About" page, controlled by HomeController/About. Which does ;)
Thanks for the help! It contributed to me understanding a bit more what was going on.
In MVC4 a default Internet Application has Authentication built-in. A class called InitializeSimpleMembershipAttribute is located in a Filters directory. As the name suggests this class Initializes the Simple Membership Database. If you look at the constructor you'll see the following line:
WebSecurity.InitializeDatabaseConnection("UserContext", "UserProfile", "UserId", "UserName", autoCreateTables: true);
Below this line you can insert the following code to create a default user:
// Create admin user.
if (!WebSecurity.UserExists("admin"))
{
WebSecurity.CreateUserAndAccount("admin", "12345678!");
}
Just another way to do things.
Try like this:
public class DataContextDbInitializer : DropCreateDatabaseAlways<DataContext>
{
protected override void Seed(DataContext context)
{
if (!Roles.RoleExists("Admins"))
{
Roles.CreateRole("Admins");
}
if (!WebSecurity.UserExists("admin"))
{
WebSecurity.CreateUserAndAccount("admin", "123456");
}
if (!Roles.GetRolesForUser("admin").Contains("Admins"))
{
Roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
}
}
}
and in your Application_Start:
Database.SetInitializer<DataContext>(new DataContextDbInitializer());
using (var ctx = new DataContext())
{
ctx.Database.Initialize(true);
}
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName",
autoCreateTables: true
);