Using attribute routing on a controller is forcing me to manage all routes - asp.net-core

I am just getting to grips with Asp.net Core and I'm trying to set up a basic site.
I want to build an admin panel that is under a subdirectory.
I have a simple controller which was scaffolded by the EF crud feature.
So it seems that from the examples I should just be able to add a [Route()] attribute to the controller and it will prefix everything. Something like this:
[Route("Admin/Subfolder/[controller]")]
public class EventsController : Controller
{
}
But when I do that I just get an error page saying "multiple actions matched" and it lists index, details, create, etc.
I can get it working if I then go through every method and put a [Route()] attribute on it but this doesn't seem to be in line with the documentation.
It feels like I should be able to just add a prefix to the controller route without having to take over management of every route within the controller. Case in point, the POSTS are not working now and I'm not sure what the format of the route attribute should be for them.
What am I doing wrong?

You are doing it correctly. Default route attribute can be applied at the controller level. “Placing a route attribute on the controller makes all actions in the controller use attribute routing.”
Can you post complete code of your controller? There must be something else going on in there. Make sure you use HttpPost/HttpGet attribute for actions with the same name, like so:
[Route("Admin/Subfolder/[controller]")]
public class EventsController : Controller
{
[HttpGet]
public IActionResult NewEvent()
{ }
[HttpPost]
public IActionResult NewEvent()
{ }
}
Good explanation on routing can be found here

Related

Access Views and Controllers which are under Sub folders for specific scenarios?

On my all actions methods I use this route attribute to use - sign.
[HttpPost]
[Route("lower-case-converter")]
public IActionResult Index(BassModel model)
Since I have many case converters I want to put them inside a folder called "CaseConverters". I made a folder in views folder called ""CaseConverters". Note that there are other tools too.
So I changed the route attribute like this
[Route("~/CaseConverters/lower-case-converter")]
Above not worked. So I changed it to
[Route("/CaseConverters/lower-case-converter")]
Still its not working. Note that i want to add this folder to Controllers folder too. How to acehve this?
To specify a route for lower-case-converter action inside your CaseConverters controller you can specify the route as follows, (I'm assuming CaseConverters is your controller. If yes It's better to use the correct naming convention. Ex: CaseConvertersController)
[Route("CaseConverters/lower-case-converter")]
You can also specify a route template for your controller class. as follows,
[Route("CaseConverters")]
public class CaseConvertersController : Controller
{
[Route("lower-case-converter")]
public IActionResult LowerCaseConverter()
{
//you implementation
}
}
For the above code route template for the action is CaseConverters/lower-case-converter. And also make sure use have used app.UseMvc() and MapRoute() methods inside Configure() method inside the startup.cs

How can I use "For" Keyword in IActionResult name of .net core?

As google suggest in this page:
https://support.google.com/webmasters/answer/7451184?hl=en
Simple URLs should convey content information
My product name is tools for car,so my url is http://localhost:4413/Product/tools-for-car
Now the problem is in the Controller,when I use this name in controller,Visual Studio report error for the keyword "For" as below:
I wonder if there is a way that I can use this url name?Or I can only change the name.Thank you.
What you probably want is to specify the routes explicitly:
[Route("[controller]")]
public class ProductController : Controller
{
[Route("tools-for-car")]
public IActionResult CarTools() { … }
}
See the Routing to controller actions documentation for more detail.

Piranha CMS on existing MVC 5 site

I am new to Piranha CMS (and in any CMS in general). I have a question about integrating the system to an existing MVC 5 application. Here is what I have done so far:
I have followed the steps in the Getting Started section
I have created the database and set up the connection string
I have created the admin user and can log in to the manager interface
What I am having trouble is understanding how to bring my existing pages into the manager and how to expose them to the users for editing. I did look into the documentation, but could not find anything dedicated to this topic.
Any help is greatly appreciated.
Thank you.
Daniel D.
It's really simple getting data from Piranha CMS into your existing application.
1. Page types
First of all, take a look at the different page types you need to create (i.e the different kind of page structures you need) and create them, either from the manager interface or by code. You'll find the docs here:
http://piranhacms.org/docs/pages/page-types
http://piranhacms.org/docs/extend/page-post-types
2. Create your pages
Next up, just create the pages you need in the manager and add the content. If you want to prohibit the users to add pages, you can always remove the "Add" buttons later, either by injecting CSS into the manager or by customizing it.
3. Adding the data to your models
Here you have two options, either you let your model inherit from the PageModel, or your just add a new property with the CMS data to your existing model.
// With inheritance
public class MyModel : Piranha.Models.PageModel {
...
}
// With the CMS data in a property
public class MyModel {
public Piranha.Models.PageModel CMSData { get; set; }
}
4. Getting the data
Now populating the data is just a calling a method. You can either access it by id or by permalink. Let's for example access it by permalink and let's say we have a page with the permalink about-us. Just add the following to your controller:
// With inheritance
public class MyController : Controller {
public ActionResult MyAction() {
// Get the CMS-data
var model = Piranha.Models.PageModel.GetByPermalink<MyModel>("about-us");
// Fill the model with your custom data
...
}
}
// With the CMS data in a property
public class MyController : Controller {
public ActionResult MyAction() {
// Create and fill your custom model
var model = new MyModel();
...
// Get the CMS-data
var model.CMSData = Piranha.Models.PageModel.GetByPermalink("about-us");
}
}
5. Configuration
Note that if you want your application to control the routing your should configure Piranha CMS to run in passive mode. You can find the docs on configuration here:
http://piranhacms.org/docs/api-reference/configuration
I hope this helps you get started!
Regards
/Håkan

initialize simple membership in MVC 4

I have a problem with my MVC 4 application which used to work fine, but stopped for some reason, and I cannot find out why. I use simple memebrship provider and code first approach. This is my Index action method in the home controller
[Authorize]
public class HomeController : Controller
{
private IActivityRepository repo;
public HomeController(IActivityRepository activityRepository)
{
repo = activityRepository;
}
//Allow anonymous to allow to create database if there isn't one yet
[AllowAnonymous]
public ActionResult Index()
{
repo.InitializeDatabase(); //!!!!!!!!!!!!!!!!!!!!!
return RedirectToAction("ManageActivities");
}
The whole concept of mine is that if database doesn't exist it gets created in InitializeDatabase Method. Then user is redirected to ManageActivities action method which is decorated with [Authorize] attribute, what in effect takes user to login action method in AccountCotroller (out of the box in MVC4). This controller is decorated with [InitializeSimpleMembership], what fires InitializeSimpleMembershipAttribute filter.
This logic worked fine for me a while ago. Today I wanted to create a new database for testing purposes. When I create data context I call the base class with a custom name for the database like so:
public class ActivityLogContext : DbContext
{
public ActivityLogContext() : base("ActivitiesConnection")
{
}
So I've changed details for my connection string and run the application. Unfortunatelly, for some reason the code hits InitializeSimpleMemebership filter before running Index method from the home controller (even though its decorated with [AllowAnonymous]). In effect simple membership is initialized but database does not yet exist, what runs me into error.
My question is, why InitializeSimpleMemebership filter is getting released on application start if Index method doesn't require authorization?
I would eliminate the use of the InitializeSimpleMembership as discussed in this article. Move initialization to the Global.asax Application_Start method and do your initialization there also, so that it happens in the correct sequence.

MVC 4 is overwriting specific Action-Parameters

MVC 4 does present me some strange behaviour at the moment.
Imagine the following Code:
TestController.cs
public class TestController : Controller
{
public ActionResult Index(Function function, string action)
{
return View();
}
public class Function
{
public string Action { get; set; }
}
}
It seems, that when I call the URL directly through the browser (localhost:PORT/Test), the Action-Property gets automatically filled with "Index".
If the Action would be named "MySuperDuperActionWhichGetsInvokedQuiteOften", exactly this Methodname would be in the property.
Can somebody explain what MVC is doing here?
The Problem is, that I of course want to fill that stuff myself, for example through an AJAX-Query. But if MVC is filling in this property all by itself, this breaks some behaviour.
I could, of course, just rename my property and it would be working, but it would still be quite interesting what's going on.
EDIT
I would understand it that my second parameter, string action, get's filled with the method-name. But why on earth would MVC bind any property/parameter that is named the same to the request-value of it?
It is problem with default model binder. It "maps" request fields to properties in your class. There is an article of MSDN describing how does it works but to simply this situation the code will be like this:
Action = Request["action"] //where of course Request["action"] equals to name of your action