I have my middleware and inside it I am trying to reach the current url of the page. so I did something like that:
$url = Request::url();
and I used:
use App\Http\Requests;
use Illuminate\Http\Request;
but I keep getting the following error:
Non-static method Illuminate\Http\Request::url() should not be called statically, assuming $this from incompatible context
any ideas?
You can access the url from the Request Object:
public function handle($request, Closure $next)
{
$url = $request->url();
...
}
Request object has also fullUrl() and path() methods. Choose the one that fit your needs
In Laravel 5 the request is already passed into the handle() function
class MyMiddleware {
public function handle($request, Closure $next)
{
$url = $request->url();
// Do stuff here
return $next($request);
}
}
Laravel 5 tries to move away from facades (e.g: Calls such as Request::url()) in favour of using dependency injection, so you may notice some functions and such cannot be accessed the same as you did in 4.
Heres quite a nice explanation of dependency injection in Laravel 5 https://mattstauffer.co/blog/laravel-5.0-method-injection
Related
I am trying to create a backend server with Aqueduct in dart. I am trying to create a resource controller that will deal with account issues.
routing code is like this;
router
.route("/$apiEntryPointUrl/account/:operation").link(() => AccountController(context, authServer));
When I try to test routers path variables like this;
#Operation.post("asdf")
Future<Response> test() async {
return Response.ok("testsuccess");
}
#Operation.post("operation")
Future<Response> test5() async {
return Response.ok("bugsuccess");
}
#Operation.post("test3")
Future<Response> test2() async {
return Response.ok("testsucces3333s");
}
When I add Operation.post("operation") as path variable, anything I pass into variable goes to this function. If I do a post request to like /account/tes2 it invokes test5() function. Is this normal? Am I missing some basics?
Actually yes, that's normal and intended. If you specify something like this: '/account/:operation' or '/account/:id' in your router then you end up with a kinda wild card, which is in these example cases 'operation' or 'id'.
The operator ':' acts as a wild card operation. This means in fact an api call to a route like '/account/tes2' will call the wild card route automatically.
My GET method WORKS fine when I use the url logged in as SuperUser like this(I get the name of the first user pulled from the DB):
http://localhost/DesktopModules/AAAA_MyChatServer/API/ChatApi/GetMessage
But I cannot access the POST method in the same controller either using AJAX from view or just by entering the url (post method doesnt get hit/found):
http://localhost/DesktopModules/AAAA_MyChatServer/API/ChatApi/SendMessage
And also this fails as well:
$('#sendChat').click(function (e) {
e.preventDefault();
var user = '#Model.CurrentUserInfo.DisplayName';
var message = $('#chatBoxReplyArea').val();
var url = '/DesktopModules/AAAA_MyChatServer/API/ChatApi/SendMessage';
$.post(url, { user: user, message: message }, function (data) {
}).done(function () {
});
});
The Error message is:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost/DesktopModules/AAAA_MyChatServer/API/ChatApi/SendMessage'.
</Message>
<MessageDetail>
No action was found on the controller 'ChatApi' that matches the name 'SendMessage'.
</MessageDetail>
</Error>
And sometimes:
"The controller does not support GET method"
even though I do have both a GET and a POST there and the GET works. What am I missing?
I have made a routing class in my DNN project:
using DotNetNuke.Web.Api;
namespace AAAA.MyChatServer
{
public class RouteMapper : IServiceRouteMapper
{
public void RegisterRoutes(IMapRoute mapRouteManager)
{
mapRouteManager.MapHttpRoute("MyChatServer", "default", "{controller}/{action}", new[] { "AAAA.MyChatServer.Services" });
}
}
}
I added a DNN Api Controller in folder Services of my project named AAAA.MyChatServer:
using DotNetNuke.Web.Api;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
namespace AAAA.MyChatServer.Services
{
[DnnAuthorize(StaticRoles = "SuperUser")]
public class ChatApiController : DnnApiController
{
[HttpGet]
public HttpResponseMessage GetMessage()
{
ChatServerManager csm = new ChatServerManager();
var users = csm.GetAllUsers();
var user = users.FirstOrDefault().Name;
return Request.CreateResponse(System.Net.HttpStatusCode.OK, user);
}
[System.Web.Http.HttpPost]
public HttpResponseMessage SendMessage(string toUser, string message)
{
return Request.CreateResponse(System.Net.HttpStatusCode.OK);
}
}
}
There are two ways to call a POST method in a DNN WebAPI: with parameters and with an object. If you use parameters, as you have in your SendMessage method, those parameter values need to be delivered via the Query String.
On the other hand, creating an object and sending that with your call to the WebAPI method can handle a great many more scenarios and is arguably a better way of handling any POST method (as it hides those values from prying eyes, making the call more difficult to counterfeit). To handle this, you can remove the parameters from your SendMessage method and instead interrogate the HttpContext.Current.Request object within your method. The object you created { user: user, message: message } will be nestled in there somewhere.
As it is written in your example, your object was sailing past your parameters like two ships in the night.
I've only just figured this out myself, and I don't have all the understanding I need yet, but hopefully this will help you along your way. Here are some articles I referenced in my quest to use cURL to upload a file to my DNN WebAPI:
https://www.dnnsoftware.com/community-blog/cid/134676/getting-started-with-dotnetnuke-services-framework
https://www.dnnsoftware.com/community-blog/cid/144400/webapi-tips
How To Accept a File POST
https://forums.asp.net/t/2104884.aspx?Uploading+a+file+using+webapi+C+
https://talkdotnet.wordpress.com/2014/03/18/dotnetnuke-webapi-helloworld-example-part-one/comment-page-1/
http://dnnmodule.com/Article/ArticleDetail/tabid/111/ArticleId/511/Dotnetnuke-7-0-WebAPI-Tips.aspx
How to post file using Curl in WebApi in Asp.Net MVC
Good luck!
Your Web Api for SendMessage contain 2 parameter, so it should POST in query string :
http://localhost/DesktopModules/AAAA_MyChatServer/API/ChatApi/SendMessage?touser=john&message=hello
if you want to POST it using data of object, you need to make the Web Service parameter as object model
Also your javascript parameter is different from the Web Service, as it use "toUser"
With WebJobs 3.0, they propose to use the Dependency Injection via ConfigureServices()
However, the services added with AddScoped() are behaving the exact same way as AddSingleton(): they are configured for the lifetime of the WebJob. I would prefer to have it scoped per function call. How can we achieve this?
I tried to use my custom job activator and do something like this:
public T CreateInstance<T>()
{
using (var scope = _service.CreateScope())
{
var service = scope.ServiceProvider.GetService<T>();
return service;
}
}
However, this gives me the following error:
The operation cannot be completed because the DbContext has been disposed.
The initialization is disposed before any call is made. I can't find how to connect this scoping mechanism properly.
The goal is to do have scoped dependency per function. At the moment, this is the only work around found to fix this issue.
public async Task SendEmail(
[QueueTrigger("%AzureStorage:Queue:SendEmail%")] int emailId,
ILogger logger
)
{
// Ugly workaround that I have to insert in all my functions.
using (var scope = serviceProvider.CreateScope())
using (var myService = scope.ServiceProvider.GetService<IMyService>())
{
await myService.SendEmailAsync(emailId);
}
}
This is my unit test for create function :
public function testCreate() {
$this->routeMatch->setMatchedRouteName('restful');
$this->request->setMethod('POST')
->setContent('name=A');
$result = $this->controller->dispatch($this->request);
$response = $this->controller->getResponse();
$this->assertEquals(403, $response->getStatusCode());
$this->assertArrayHasKey('id', $result);
}
And this is my function :
public function create($data) {
if (empty($data)) {
$this->response->setStatusCode(400);
return;
}
for ($i = 0; $i < count(self::$ideas); $i++) {
if (self::$ideas[$i]['name'] == $data['name']) {
$this->response->setStatusCode(404);
return;
}
}
//#todo: secure the API
self::$index++;
$tmpArray = array('id'=>self::$index, 'name'=>$data['name']);
$this->response->setStatusCode(403);
}
But it seems that the $data is always blank. Am I wrong at the part writing unit test ?
When I try to use curl POST with -d, the $data has value as what I post through curl. I'm a quite confused what is wrong here ?
Thanks for reading and looking forward to your answer :)
Answer
I've came up with my successful unit test http://pastebin.com/fwFe0Mi3
For more information, I use this module to implement restful controller
If you take a look at \Zend\Mvc\Controller\AbstractRestfulController method processPostData you will notice that the method create in your controller is given an array of the post params from the request object.
If you look at \Zend\Http\Request the $postParams property is populated by the setPost method.
Now the child class \Zend\Http\PhpEnvironment\Request (used by ZF2 when you are requesting something) that extends \Zend\Http\Request (above) on instantiation (__contruct method) calls the setPost method (above) giving it the $_POST array.
This means that eventually ZF2 internally feeds your controller's create method with the $_POST contents and not by parsing the request body.
Now to your code.
I don't think dispatch will do anything without you having set up the event framework first. Instead you can call the controllers execute method providing it with an MvcEvent. The MvcEvent needs to have the request you instantiated set.
Secondly, as described above you need to call the request's setPost and give it an array for the create method to work properly. (On the other hand PUT reads the data from the request body)
Try doing that and if you are still having trouble I will try and give you an example soon.
I registered my services.yml file like below :
services:
PMI.form.users_tasks:
class: PMI\UserBundle\Form\UsersTasksType
arguments:
EntityManager: "#doctrine.orm.default_entity_manager"
I can list it by php app/console container:debug, so that mean my service is registered properly.
In my UsersTasksType class I have like below :
class UsersTasksType extends AbstractType
{
protected $ur;
public function __construct(EntityManager $ur )
{
$this->setUr($ur);
}
// Get and setters
}
Does Dependency Injection mean that I don't have to pass the EntityManager to the class constructor anymore? Or what ?
Because when I have to run the code below :
$form = $this->createForm(new UsersTasksType(), $entity);
I get this error:
Catchable Fatal Error: Argument 1 passed to PMI\UserBundle\Form\UsersTasksType::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in C:\wamp\www\PMI_sf2\src\PMI\UserBundle\Controller\UsersTasksController.php on line 74 and defined in C:\wamp\www\PMI_sf2\src\PMI\UserBundle\Form\UsersTasksType.php line 19
And I have to do something below :
$em = $this->container->get('doctrine.orm.entity_manager');
$form = $this->createForm(new UsersTasksType($em), $entity);
So what would be the whole purpose of Dependency Injection ?
Dependency Injection basically gives one service (in this case, your UserTasksType) access to another service (in this case, your the entity manager).
arguments:
EntityManager: "#doctrine.orm.default_entity_manager"
These two lines tell Symfony to expect the entity manager service to be passed into the constructor when you instantiate a new UserTasksType object, which effectively gives your UserTasksType access to the entity manager.
If you aren't using the entity manager in your UserTasksType, there is no need to inject it in the constructor and you could get rid of the two lines above and the __construct() / setUr() methods in your UserTasksType.
A better example to help you understand DIC might be that you have a service that is written specifically to send emails (Swiftmail, for e.g.) and you need to inject it into another service so that service can send emails.
By adding
arguments: [ #mailer ]
to your service definition, your services constructor will expect your mailer service
__construct ($mailer)
{
$this->mailer = $mailer;
}
which will give it access to send emails
someFunction()
{
//do something useful, then send an email using the swift mailer service
$this->mailer->sendEmail();
}
Check out the latest Symfony docs for more of an explanation.
http://symfony.com/doc/current/book/service_container.html