What I'm trying to do is look directly at the incoming web request and manually select a controller to handle it. So far, I have created a custom implementation of IControllerFactory, but it seems that this runs after routing. Since the requests that are coming in don't match a route registered with MVC, it immediately goes to 404.
What I'm trying to figure out is how I can skip the routing portion straight to IControllerFactory step.
This sounds super odd, but I'm doing a proof of concept on creating routes at runtime. The idea is that, at runtime, I can download and load an assembly that has some controllers in it (i.e. a plugin) and then attempt register the route without restarting the service. I have most of it worked out I think, but I'm trying to figure out the routing part and it seemed easiest to simply grab the request and manually select the controller.
I've looked into implementing IRouter and then using app.UseRouter(myRouter) but I couldn't quite find what I was looking for.
Suggestions?
Related
I'm creating a new application in Zend Framework 3 and i have a question about a design pattern
Without entering in much details this application will have several Services, as in, will be connecting to external APIs and even in multiple databases, the workflow is also very complex, a single will action can have multiple flows depending on several external information (wich user logged in, configs, etc).
I know about dependency injections and Zend Framework 3 Service Manager, however i am worried about instanciating sereval services when the flow will actually use only a few of them in certain cases, also we will have services depending on other services aswell, for this, i was thinking about using singletons.
Is singleton really a solution here? I was looking a way to user singletons in Zend Framework 3 and haven't figured out a easy way since i can't find a way to user the Service Manager inside a service, as I can't retrive the instance of the Service Manager outside of the Factory system.
What is an easy way to implement singletons in Zend Framework 3?
Why use singletons?
You don't need to worry about too many services in your service manager since they are started only when you get them from the service manager.
Also don't use the service manager inside another class except a factory. In ZF3 it's removed from the controllers for a reason. One of them is testability. If all services are inject with a factory, you can easily write tests. Also if you read your code next year, you can easily see what dependencies are needed inside a class.
If you find there are too many services being injected inside a class which are not always needed you can:
Use the ProxyManager. This lazy loads a service but doesn't start it until a method is called.
Split the service: Move some parts from a service into a new service. e.g. You don't need to place everything in an UserService. You can also have an UserRegisterService, UserEmailService, UserAuthService and UserNotificationsService.
In stead of ZF3, you can also think about zend-expressive. Without getting into too much detail, it is a lightweight middleware framework. You can use middleware to detect what is needed for a request and route to the required action to process the request. Something like this can probably also done in ZF3 but maybe someone else can explain how to do it there.
I'd read it somewhere that whenever one needs to do data intensive work then Webapi could be used. Ex: autocomplete textbox where we get data from using ajax on key press.
Now someone told me that Webapi shouldn't be used within applications which are not externally accessed. Rather action should be used to the same work as it is capable of returning the data back in a similar fashion to webapi.
I'd like to know your suggestions over it.
Depends on how you look at it. If all you need is ajax-ification of your controller actions, then you really don't need Web-API. Your actions can return a JsonResult and it is very easy to consume that from your client side through an AJAX call.
Web-API makes it easy for you to expose you actions to external clients. It supports HTTP protocol and Json and XML payloads automatically, out of the box, without you writing the code for it. Now, there is nothing preventing you from consuming the same Web-API actions from your own internal clients in an AJAX manner.
So the answer to your question depends on your design. If you don't have external clients, then there is no string need for you to have Web-API. Your standard controller actions can do the job.
Im creating an API using Java and Spring. My question is, is there a standard way to organize the API routes into one file?
For example when creating an API using Express.JS there is one file, called the router, where all of the routes are declared and set up.
With Spring's annotation-based MVC framework it seems like the routes are scattered through various controllers. So if someone who didn't write the API needed to make changes to it they would be left searching through files to find the specific route.
Is there a standard practice or pattern that would create a central router? Im thinking about just creating a router class however I would then have to create instances of MANY classes in that router. It doesn't seem very clean.
XML configuration used to be the only way to do it, but if I remember correctly, the usual usage was to have one method per controller.
There's a fairly nice implementation of what you're looking for in the third-party springmvc-router project, which will let you configure your routes something like:
GET /user/? userController.listAll
GET /user/{<[0-9]+>id} userController.showUser
DELETE /user/{<[0-9]+>id} userController.deleteUser
POST /user/add/? userController.createUser
I would like to ask whether it's a good approach to redirect from within a model instead of a controller.
The reason I want to do that is because it is easier to unit test redirection from a model (I just pass a mock redirector object to the model in my tests) as opposed to controller which is more difficult to unit test. It also keeps controller thinner as all I do in the controller is create an instance of the model and pass it parameters from the request object. There is not a single if/else in the controller this way.
Is it a bad practise?
Most often in webapplications - MVC or not - redirects are implemented on a high-level layer. In non OOP code this often is a high level global function that knows a lot about the global static state and what represents a request and a response therein.
In more OOP driven sites, you find this often as a method with the "response" object (compare Symfony2 and HTTP Fundamentals; note that Symfony2 is not MVC), however, it often then has also some similar methods (e.g. see Difference between $this->render and $this->redirect Symfony2).
As most often those "response" objects are central in the web-application this qualifies as well as a high-level layer in my eyes.
From a testing standpoint - especially with integration testing - you normally do not need to test for redirects specifically. You should test that generally your redirect-functionality works on the HTTP layer so that parts of your application that make use of it can rely on it. Common problems are to not really follow the suggestions given in the HTTP/1.1 specs like providing a response body with redirects. A well working webapplication should honor that. Same for using fully qualified URIs.
So how does all fit this into MVC here? In a HTTP context this could be simplified as the following:
The response is to tell the user to go somewhere else.
If the user would not be important, the application could forward directly - that is executing a different command, the client would not be used for that, the redirect not necessary (sub-command).
The response is to say: Done. And then: See next here this command (in form of an URI).
This pretty much sounds like that the actual redirect is just some output you send to the client on the protocol level in client communication. It belongs into the interface of that protocol you want to support. So not into the model but into the client-interface and the boundary of the client interface inside an MVC application is the controller AFAIK.
So the redirect probably is a view-value-object with a special meaning. To get that working in a HTTP MVC you need a full URL abstraction which most PHP frameworks and libraries make a big round around because it's not well known how that works. So in the end I'd say: Do as Symfony2 has done, place it in a high level layer component, drop MVC and live with the deficiencies.
Everything else is hard to achieve, if you try otherwise, there is high risk to not stop with abstracting anymore.
Neither controller nor model should be redirecting anything anywhere. HTTP Location header is form of a response, which strictly in purview of views.
Model layer deals with business logic, it should be completely oblivious even to the existence of presentation layer.
Basically, it goes down to this: controllers handle input, views handle output. HTTP headers are part of output.
Note: when dealing with Rails clones, it is common to see redirects performed in "controller". It is because what they call "controller" is actually a merger of view and a controller responsibilities. This is a side-effect of opting to replace real views with simple templates as the 3rd side of triad.
I would say yes, it is wrong. As far as I understood, while models manage data and views manage layouts (i.e. how data should be displayed), controllers are only and exclusively in charge of the HTTP requests/responses management (in the case of a web app), and redirections typically belong to that tier in my opinion.
Examples in common frameworks
Symfony:
return $this->redirect($this->generateUrl('homepage'));
Spring MVC:
return "redirect:/appointments";
I think that you could have a model for your applications work flow or navigation (in your model layer) and then have your controller translate the different concepts in your work flow/navigation model into what views are to be displayed.
Your work flow class/module could know about the different activities/phases/steps that are available to the user, and it model your application kind of like a state machine. So your controller would make calls to this module to update the state and would recieve a response telling the controller which activity/phase/step it should go to.
That way your work flow model is easy to test but it still doesn't know about your view technology.
Many mentioned in comments these thoughts, so here is a summary:
The logic to figure out whether you need a redirect and what your redirect should be belongs into the controller. The model simply takes the data a view needs. This happens AFTER you decided which view to render. Think of the redirect as an instruction to perform a different controller action.
I use ASP.NET MVC and the controllers generate a RedirectResult for this purpose, which are completely unit testable. I don't know what is supported in your framework, but this is what MVC would do:
public class MyController : Controller {
public ActionResult ShowInfo(string id) {
if( id == null ) {
return new RedirectResult("searchpage");
} else {
return new ViewResult("displayInfo");
}
}
}
In your unit tests, you instantiate MyController and check the type of the result and optionally, the url or view name.
Whether your redirect is actually performed is not a unit test issue - that's essentially making sure your framework is working right. What you need to test is that you are giving the correct instruction (i.e. the redirect) and the correct url.
I'm having an issue that, while not critical, still called my attention.
I happen to have an MVC4 web application where I've replaced the default controller factory for one implemented by myself, within this factory I use unity to inject the constructor parameters for the controller.
What I don't understand is why, for each and every request I make, the CreateController method gets called for every controller in the application and not just the one in the url and the ones called by partial views.
Is that behaviour normal? Is it necessary or is there a way to prevent it?
I see no reason for this and my research hasn't lead me to any good answer.
Thanks!
Ha! It turns out that when you use mvc sitemap solution it builds every controller for every request, by removing this line, that weird behaviour didn't happen anymore
#Html.MvcSiteMap().SiteMapPath()
Thanks anyway for the ones who read this and I hope someone finds this useful!