I am trying to make custom post request with BrowserClient (package:http/browser_client.dart) using send method. I don`t understand how should i extend abstract BaseRequest, should i override finalize method?
Unless you're doing something very custom, you want to use one of the subclasses of the abstract BaseRequest class (seen in the docs under Implemented by).
I'm almost sure you want to just use the Request class, like so:
var client = new BrowserClient();
var request = new Request("post", Uri.parse("http://example.com"));
// ... set up the request some more ...
var response = await client.send(request);
// ... do stuff with response ...
Related
I have a Web Api that takes a complex object and adds it to the database.
var myWidgit= new Widgit() {
Name = "WidgitName",
Price = 50,
Category = "Appliance" };
HttpResponseMessage response = client.PostAsync("api/createwidgit", myWidgit);
I need to make a one off call to the API and I would like to avoid creating a separate class file for Widgit.
Is there a way to define the Widgit class and assign it values in the method that makes use of it? Sort of like a dynamic class just used in this method.
I think I figured it out ...
HttpResponseMessage response = client.PostAsync("api/createwidgit", new StringContent(string.Format("Name={0}&Price={1}&Category={2}", HttpUtility.UrlEncode("WidgitName"), HttpUtility.UrlEncode(50), HttpUtility.UrlEncode("Appliance"), Encoding.UTF8, "application/x-www-form-urlencoded"));
Essentially the dynamic object I was looking to create is accomplished using
new StringContent(string.Format("Name={0}&Price={1}&Category={2}", HttpUtility.UrlEncode("WidgitName"), HttpUtility.UrlEncode(50)), HttpUtility.UrlEncode("Appliance"), Encoding.UTF8,
"application/x-www-form-urlencoded")
Sorry I could not figure out better formatting
My web app is using PKI authentication via a piv card. I grab the user's unique identifier information via HttpClientCertificate.Subject. The problem is that when I am unit testing, mock will not mock this class since it doesn't have a constructor. I tried following the advice on this thread:
How to mock HttpClientCertificate?
but it looks like the way he sets it up is to inject the client certificate through the controller's constructor which I dont' want to do since the controller already has access to the client certificate. I'm assuming thats what he is implying since he is using some type of adapter pattern. Anyone got any better sugguestions?
Why don't you wrap it into your own object?
class MyHttpClientCertificate
{
public MyHttpClientCertificate(HttpClientCertificate foo) { ... }
internal MyHttpClientCertificate() { ... }
}
Your issue is that the code is using the Request object to get the certificate, but that's not easily unit testable.
What I would do is add a function delegate that, by default, will use the Request object to return the HttpClientCertificate, but will allow overriding the implementation.
For the controller, add this:
internal Func<HttpClientCertificate> HttpClientCertificateGetter = () => {
return Request.ClientCertificate;
}
And in your Controller instead of using Request use HttpClientCertificateGetter.
Then in your unit test you mock the certificate and assign it to the getter function, like this:
var certMock = new Mock<HttpClientCertificate>();
HttpClientCertificate clientCertificate = certMock.Object;
requestMock.Setup(b => b.ClientCertificate).Returns(clientCertificate);
certMock.Setup(b => b.Certificate).Returns(new Byte[] { });
controller.HttpClientCertificateGetter = () => {certMock.Object};
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.
So I'm creating a custom ActionFilter that's based mostly on this project http://www.codeproject.com/KB/aspnet/aspnet_mvc_restapi.aspx.
I want a custom action filter that uses the http accept headers to return either JSON or Xml. A typical controller action will look like this:
[AcceptVerbs(HttpVerbs.Get)]
[AcceptTypesAttribute(HttpContentTypes.Json, HttpContentTypes.Xml)]
public ActionResult Index()
{
var articles = Service.GetRecentArticles();
return View(articles);
}
The custom filter overrides the OnActionExecuted and will serialize the object (in this example articles) as either JSON or Xml.
My question is: how do I test this?
What tests do I write? I'm a TDD novice and am not 100% sure what I should be testing and what not to test. I came up with AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson(), AcceptsTypeFilterXml_RequestHeaderAcceptsXml_ReturnsXml() and AcceptsTypeFilter_AcceptsHeaderMismatch_ReturnsError406().
How do I test an ActionFilter in MVC that is testing the Http Accept Headers?
Thanks.
You just need to test the filter itself. Just create an instance and call the OnActionExecuted() method with test data then check the result. It helps to pull the code apart as much as possible. Most of the heavy lifting is done inside the CsvResult class which can be tested individually. You don't need to test the filter on an actual controller. Making that work is the MVC framework's responsibility.
public void AcceptsTypeFilterJson_RequestHeaderAcceptsJson_ReturnsJson()
{
var context = new ActionExecutedContext();
context.HttpContext = // mock an http context and set the accept-type. I don't know how to do this, but there are many questions about it.
context.Result = new ViewResult(...); // What your controller would return
var filter = new AcceptTypesAttribute(HttpContentTypes.Json);
filter.OnActionExecuted(context);
Assert.True(context.Result is JsonResult);
}
I just stumbled upon this blog post which seems the right way to me. He uses Moq.
What this chap is doing is mocking the HTTPContext, but also we need to set up a ContentType in the request:
// Mock out the context to run the action filter.
var request = new Mock<HttpRequestBase>();
request.SetupGet(r => r.ContentType).Returns("application/json");
var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Returns(request.Object);
var routeData = new RouteData(); //
routeData.Values.Add("employeeId", "123");
var actionExecutedContext = new Mock<ActionExecutedContext>();
actionExecutedContext.SetupGet(r => r.RouteData).Returns(routeData);
actionExecutedContext.SetupGet(c => c.HttpContext).Returns(httpContext.Object);
var filter = new EmployeeGroupRestrictedActionFilterAttribute();
filter.OnActionExecuted(actionExecutedContext.Object);
Note - I have not tested this myself.
I'm trying to implement a SoapExtension for log purposes (print the xml soap request) on an .NET 2.0 client application (not ASP.NET).
I first tried a simple console application just to check and I'm not able to see that the extension is called.
The simple code is just two lines:
System.Net.WebRequest request = System.Net.WebRequest.Create("http://www.ynet.com");
WebResponse response = request.GetResponse();
and my config file is the following:
What I'm doing wrong? are the extension usable only in ASP.NET?
Thanks
You must have class e.g.:"YourExtension" derived from "SoapExtension" class and attribute class e.g. "YourExtensionAttribute" derived from "SoapExtensionAttribute" there you overide "Type" property:
public override Type ExtensionType
{
get { return typeof(YourExtension); }
}
and put SoapExtensionAttribute to your webservice method