I'm looking to create a framework only SilverStripe website, however I have been unable to correctly set up the routing for it.
I want to have a single controller handling a handful of URLs. I want it to handle an empty URL too, i.e. '/'.
I've been unable to get my controller to differentiate between the different urls.
My routes are as follows:
---
Name: rootroutes
---
Director:
rules:
'$Action/$ID/$OtherID': 'MainController'
'': 'MainController'
and my controller:
class MainController extends Controller {
private static $url_handlers = array(
'$Action//$ID/$OtherID' => 'handleAction',
);
public function index() {
return "index";
}
public function login() {
return "login";
}
public function handleAction($request, $action) {
var_dump($action); // always 'index'
if($this->hasMethod($action)) {
return $this->$action();
}
}
}
You need to define the $allowed_actions array on your controller before actions other than index() will work.
Related
Hello i am working on asp.net core 2.2 web api , my get request is working fine but i am having problem in HTTPDELETE request, my code for the delete request is as follows
[Route("api/[controller]")]
[ApiController]
public class PatientController : ControllerBase
{
IPatientManager _patientManager;
IEnumerable<Patient> patientList;
public PatientController(IPatientManager patientManager)
{
_patientManager = patientManager;
}
[HttpGet]
public IEnumerable<Patient> Get()
{
return (patientList = _patientManager.GetAllPatients());
}
// DELETE api/values/5
[HttpDelete("api/Patient/{id}")]
public bool Delete(long id)
{
if (_patientManager.DeletePatient(id))
return true;
else
return false;
}
}
}
when i put the request in URL as localhost:3, n922/api/Patient/444373 it gives me HTTP ERROR 404 , my startup.cs file is using the below code for MapRoute
app.UseMvc(opt =>
{
opt.MapRoute("Default",
"{controller=Patient}/{action=Get}/{id?}");
});
to start the my PatientController instead of ValuesController, Please help what is problem where i am doing wrong? TIA
You have a route prefix defined on your controller as api/[controller], which translates to /api/Patient. Then, your route on your action is defined as api/Patient/{id}, which makes the entire route to this action: /api/Patient/api/Patient/{id}. That's obviously not right and is the source of your 404. Change the route to just {id}.
[HttpDelete("{id}")]
public bool Delete(long id)
I get this error, when I'm trying to run the site.
The controller type UmbracoBootstrapProject.Controllers.SiteLayoutControllers does not follow conventions, MVC Controller class names must be suffixed with the term 'Controller'
namespace UmbracoBootstrapProject.Controllers
{
public class SiteLayoutControllers : SurfaceController
{
private const string PARTIAL_VIEW_FOLDER = "~/Views/Partials/SiteLayout/";
public ActionResult RenderHeader()
{
return PartialView(PARTIAL_VIEW_FOLDER + "_Header.cshtml");
}
public ActionResult RenderFooter()
{
return PartialView(PARTIAL_VIEW_FOLDER + "_Footer.cshtml");
}
}
}
The problem is you have named your controller SiteLayoutControllers (plural) instead of SiteLayoutController. Changing it to the latter should fix it
i am currently trying to generate this url "/Cloud/Hosting/RoaringPenguin/Manage/Exclusions".
Here is the area registration
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Hosting_default",
"Cloud/Hosting/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
here is the controller
public class RoaringPenguinController : PortalControllerBase
{
public ActionResult Exclusions()
{
return View("Exclusions");
}
}
i have tried added a route onto the action itself like so
[Route("Manage/Exclusions")]
public ActionResult Exclusions()
I have also tried adding some attributes to the controller itself
[RouteArea("Hosting")]
[RoutePrefix("RoaringPenguin")]
public class RoaringPenguinController : PortalControllerBase
but that doesn't seem to work either. If i leave all the attributes off then the final url i get is "/Cloud/Hosting/RoaringPenguin/Exclusions".
Does anyone know how i can get the "Manage" in the url as well?
Just to confirm i have the following set in my RegisterRoutes method under the RouteConfig class
routes.MapMvcAttributeRoutes();
Any help is appreciated. Thanks
Your default area route doesn't allow for the "Manage/Exclusions" part on the end. If you made the URL just /Cloud/Hosting/RoaringPenguin/Exclusions (minus the Manage part of the path) it would work fine.
If you need the route to be exactly that, then attribute routing is your best bet. However, your mentioned attempts at that are all missing something or another. Your controller should be decorated with both RouteArea and RoutePrefix to compose the first part of the path:
[RouteArea("Hosting", AreaPrefix = "Cloud/Hosting")]
[RoutePrefix("RoaringPenguin")]
public class RoaringPenguinController : Controller
However, it's typical to actually implement a base controller when dealing with areas, so that you can specify RouteArea in just one place:
[RouteArea("Hosting", AreaPrefix = "Cloud/Hosting")]
public class HostingBaseController : Controller
[RoutePrefix("RoaringPenguin")]
public class RoaringPenguinController : HostingBaseController
Then, on your action:
[Route("Manage/Exclusions")]
public ActionResult Exclusions()
As you had.
Try with this code
[RouteArea("AreaName", AreaPrefix = "Cloud/Hosting")]
[RoutePrefix("RoaringPenguin")]
public class SampleController : Controller
{
[Route("Manage/Exclusions")]
public ActionResult Exclusions()
{
return View("Exclusions");
}
}
or
[RoutePrefix("Cloud/Hosting/RoaringPenguin")]
public class RoaringPenguinController : PortalControllerBase
{
[Route("Manage/Exclusions")]
public ActionResult Exclusions()
{
return View("Exclusions");
}
}
This will be the first line
routes.MapMvcAttributeRoutes();
After that only you have to write this line
AreaRegistration.RegistrationAllAreas();
in my symfony2 project i need call the same action in many controllers and this action should return a very simple php array that then will be passed to a twig template by these controllers. How can i do it?
A pratical example can explain my situation better.
1.shared controller
// Acme/DemoBundle/Controller/MetasController
class MetasController extends Controller {
public function metasAction() {
$myArray= array();
return $myAarray;
}
}
page render controller
// Acme/DemoBundle/Controller/PageController
class PageController extends Controller {
protected $property = "test";
public function indexAction() {
$metas= $this->forward('AcmeDemoBundle:Metas:metas');
return $this->render('AcmeDemoBundle:Page:index.html.twig', array('property'=>property, 'metas'=>$metas));
}
}
when i do this i get an error: the controller must be a response array given.
You should create a service
// Acme/DemoBundle/Controller/MetasController
class MetasController {
public function metasAction() {
$myArray= array();
return $myAarray;
}
}
declare as service in Acme\DemoBundle\Resources\config\services.yml
services:
demo.metas:
class: "Acme\DemoBundle\Controller\MetasController"
Then you can use it in any other controller
// Acme/DemoBundle/Controller/PageController
class PageController extends Controller {
protected $property = "test";
public function indexAction() {
$metas= $this->get('demo.metas')->metas();
return $this->render('AcmeDemoBundle:Page:index.html.twig', array('property'=>property, 'metas'=>$metas));
}
}
In your action controller :
<?php
...
$arrayExample = array();
return $this->render('ExampleBundle:ExampleFolder:exampleTemplate', array('myArray' => $arrayExample));
And in your twig template now you have access to your array using myArray
Example :
{% for data in myArray %}
...
{% endfor %}
Try this :
use Symfony\Component\HttpFoundation\Response;
public function indexAction()
{
...
$content = $this->renderView(
'AcmeDemoBundle:Page:index.html.twig',
array('property'=> $property,
'metas' => $metas
));
return new Response($content);
}
Yes, you can register your controller as a service as it said above but I would recommend to isolate this logic in a different place. It might be a service but not controller.
As I understand you need the same array in several places. So, it might be some class registered as service or some simple class with static method providing this array. In this case your code will be much cleaner.
If you need this array only in view you can define custom twig method which will return array you need. If this array might be different time to time (if it might depend on some data) you can pass entity manager to the service providing this array or to the twig extension.
(The best use of controllers is to be just a proxy between view and data layer. It's not a good idea to use it for such purposes as you described (in my opinion of course).)
I'm using asp.net mvc 4 and web api. My route is like this:
/api/{controller}/jqGrid/{action}/{id}
for example, if the route is :
/api/User/jqGrid/List
I hope it will route to the action name "jqGrid_List" of the User controller.
How can I achieve this?
hmm, I don't know if it's acceptable to answer my own question. I found out a solution.
First of all, I need to add a JqGridControllerConfiguration attribute to replace the default action selector applied to the controller with my one.
[JqGridControllerConfiguration]
public class UserController : ApiController
{
// GET: /api/User/jqGrid/List
[HttpGet]
public JqGridModel<User> jqGrid_List()
{
JqGridModel<User> result = new JqGridModel<User>();
result.rows = Get();
return result;
}
}
Here's the code of JqGridControllerConfiguration:
public class JqGridControllerConfiguration : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new JqGridActionSelector());
}
}
in JqGridActionSelector, the "action" is modified if a "jqGrid/" exists in the request URL.
public class JqGridActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
Uri url = controllerContext.Request.RequestUri;
if (url.Segments.Any(s => string.Compare(s, "jqGrid/", true) == 0))
{
controllerContext.RouteData.Values["action"] = "jqGrid_" + controllerContext.RouteData.Values["action"].ToString();
}
return base.SelectAction(controllerContext);
}
}
Not sure why you'd want to do this. But you can still create a "jqGrid_List" action in your User controller and set an ActionName for it, and it'll work.
UserController:
[HttpGet, ActionName("List")]
public string jqGrid_List()
{
return "WORKS";
}
Your Route:
routeTemplate: "api/{controller}/jqGrid/{action}/{id}"