I have a case where it is returning objects of type T. My code looks like this.
public static T GetObjectsFromWebRequest<T>(string urlPath) where T : class
{
T modelObjects;
try
{
//SaveServiceDataIntoTextFile(urlPath);
WebRequest request = WebRequest.Create(urlPath);
WebResponse ws = request.GetResponse();
StreamReader responseStream = new StreamReader(ws.GetResponseStream());
//Get the response of the webrequest into a string
string response = responseStream.ReadToEnd();
modelObjects = XMLSerializeDeserialize.ConvertXMLToModel<T>(response);
}
catch (Exception)
{
throw;
}
return modelObjects;
}
In this case I don't have any option but add a default parameter like
public static T GetObjectsFromWebRequest<T>(string urlPath, T a = null) where T : class
Is there any other way I can resolve this violation?
As suggested here, you could use an out parameter to convey your result:
public static void GetObjectsFromWebRequest<T>(string urlPath, out T objects) ...
Related
I'm struggling with something that should be pretty basic for the professionals.
I'm trying to use an extension wrapper for httpWebRequest. the extension class looks like this:
public static class WebRequestExtensions
{
public static Stream GetRequestStreamWithTimeout(
this WebRequest request,
int? millisecondsTimeout = null)
{
return AsyncToSyncWithTimeout(
request.BeginGetRequestStream,
request.EndGetRequestStream,
millisecondsTimeout ?? request.Timeout);
}
public static WebResponse GetResponseWithTimeout(
this HttpWebRequest request,
int? millisecondsTimeout = null)
{
return AsyncToSyncWithTimeout(
request.BeginGetResponse,
request.EndGetResponse,
millisecondsTimeout ?? request.Timeout);
}
private static T AsyncToSyncWithTimeout<T>(
Func<AsyncCallback, object, IAsyncResult> begin,
Func<IAsyncResult, T> end,
int millisecondsTimeout)
{
var iar = begin(null, null);
if (!iar.AsyncWaitHandle.WaitOne(millisecondsTimeout))
{
var ex = new TimeoutException();
throw new WebException(ex.Message, ex, WebExceptionStatus.Timeout, null);
}
return end(iar);
}
}
I'm trying to use the wrapper methods GetResponseWithTimeout and GetRequestStreamWithTimeout but I don't know how to do this. The working code should look like this:
var request = (HttpWebRequest)WebRequest.Create(url);
requestStream = request.GetRequestStreamWithTimeout();
How can I achieve this?
Edit
I've tried to derive the main class from the extension class which let's me use the wrapper methods but now I'm getting this error message:
Error 3 'chunkedUpload.UploadFile': cannot derive from static class 'chunkedUpload.WebRequestExtensions'
I have this class:
public class RestClient
{
public RestClient()
{ }
protected virtual HttpWebRequest CreateHttpWebRequest(Uri uri)
{
return (HttpWebRequest)HttpWebRequest.Create(uri);
}
/// <summary>
/// Perform a http POST request in order to push data to server
/// </summary>
/// <param name="uri">End Point Uri</param>
/// <param name="data">Data to be transmitted</param>
/// <returns></returns>
///
public long PostRequest(Uri uri,string data)
{
try
{
HttpWebRequest request = CreateHttpWebRequest(uri); //(HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json";
System.Text.UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(data);
using (Stream requestStream = request.GetRequestStream())
{
//Transmit data
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Flush();
requestStream.Close();
}
//Get the Response from the server
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.NoContent)
{
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
}
}
return request.ContentLength;
}
catch (Exception e)
{
throw e;
}
}
}
And would like to Unit test (using nunit) the PostRequest Method.
Doing some research, I could found some way to mock the HttpWebRequest in this post (Is it possible to mock out a .NET HttpWebResponse?) and a way to inject it into the class in this post (How to unit test a method with HttpWebRequest/Response dependencies).
However, when I tried to test my method I got this error:
System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.IHttpWebRequestProxy' to type 'System.Net.HttpWebRequest'.
in this line of my test
client.HttpWebRequestFake = (HttpWebRequest)factory.Object.Create("http://127.0.0.1");
That is my test code:
public class TesableRestClient : RestClient
{
public HttpWebRequest HttpWebRequestFake { get; set; }
protected override HttpWebRequest CreateHttpWebRequest(Uri url)
{
if (HttpWebRequestFake != null)
return HttpWebRequestFake;
return base.CreateHttpWebRequest(url);
}
}
[TestFixture]
public class TransferWebRequestTest
{
[Test]
public void TestPostResquest()
{
string expectedContent = "Content";
var expectedBytes = Encoding.UTF8.GetBytes(expectedContent);
var responseStream = new MemoryStream();
responseStream.Write(expectedBytes, 0, expectedBytes.Length);
responseStream.Seek(0, SeekOrigin.Begin);
var response = new Mock<IHttpWebResponse>();
response.Setup(c => c.GetResponseStream()).Returns(responseStream);
var request = new Mock<IHttpWebRequest>();
request.Setup(c => c.GetResponse()).Returns(response.Object);
var factory = new Mock<IHttpWebRequestFactory>();
factory.Setup(c => c.Create(It.IsAny<string>()))
.Returns(request.Object);
TesableRestClient client = new TesableRestClient();
client.HttpWebRequestFake = (HttpWebRequest)factory.Object.Create("http://127.0.0.1");
// DoStuff call the url with a request and then processes the
long bytesSent = client.PostRequest(new Uri("http://127.0.0.1"), expectedContent);
Assert.AreEqual(expectedBytes, bytesSent);
}
The HttpWebRequest/Response is this:
public interface IHttpWebRequest
{
// expose the members you need
string Method { get; set; }
string ContentType { get; set; }
long ContentLength { get; set; }
IHttpWebResponse GetResponse();
}
public interface IHttpWebResponse : IDisposable
{
// expose the members you need
HttpStatusCode StatusCode { get; }
string StatusDescription { get;}
Stream GetResponseStream();
}
public interface IHttpWebRequestFactory
{
IHttpWebRequest Create(string uri);
}
// barebones implementation
public class HttpWebRequestFactory : IHttpWebRequestFactory
{
public IHttpWebRequest Create(string uri)
{
return new WrapHttpWebRequest((HttpWebRequest)WebRequest.Create(uri));
}
}
public class WrapHttpWebRequest : IHttpWebRequest
{
private readonly HttpWebRequest _request;
public WrapHttpWebRequest(HttpWebRequest request)
{
_request = request;
}
public string Method
{
get { return _request.Method; }
set { _request.Method = value; }
}
public string ContentType
{
get { return _request.ContentType; }
set { _request.ContentType = value; }
}
public long ContentLength
{
get { return _request.ContentLength; }
set { _request.ContentLength = value; }
}
public IHttpWebResponse GetResponse()
{
return new WrapHttpWebResponse((HttpWebResponse)_request.GetResponse());
}
}
public class WrapHttpWebResponse : IHttpWebResponse
{
private HttpWebResponse _response;
public WrapHttpWebResponse(HttpWebResponse response)
{
_response = response;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
if (_response != null)
{
((IDisposable)_response).Dispose();
_response = null;
}
}
}
public Stream GetResponseStream()
{
return _response.GetResponseStream();
}
public HttpStatusCode StatusCode
{
get { return _response.StatusCode; }
}
public string StatusDescription
{
get { return _response.StatusDescription; }
}
}
Any idea of how I could solve this?
Thank you
I solved my issue doing the follow:
First, created a interface IHttpWebRequestFactory
public interface IHttpWebRequestFactory
{
HttpWebRequest Create(string uri);
}
In the class that I want to test, I created the following methods:
protected virtual HttpWebRequest CreateHttpWebRequest(Uri uri)
{
return (HttpWebRequest)HttpWebRequest.Create(uri);
}
protected virtual HttpWebResponse GetHttpWebResponse(HttpWebRequest request)
{
return (HttpWebResponse)request.GetResponse();
}
In my test file, I created a "Testable " class, that inherits from the class I really want to test and overrides the virtual methods:
//Class Created to test the PostRequestMethod
public class TestableRestClient : RestClient
{
public HttpWebRequest HttpWebRequestFake { get; set; }
public string responseValue;
protected override HttpWebRequest CreateHttpWebRequest(Uri url)
{
if (HttpWebRequestFake != null)
return HttpWebRequestFake;
return base.CreateHttpWebRequest(url);
}
protected override HttpWebResponse GetHttpWebResponse(HttpWebRequest request)
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(request.GetResponse().GetResponseStream()))
{
responseValue = streamReader.ReadToEnd();
}
return base.GetHttpWebResponse(request);
}
}
Then I used Moq to mock the behavior of methods I'm using in my class
[TestFixture]
public class DMSTransferWebRequestTest
{
[Test]
public void TestPostResquest()
{
string expected = "Content";
//Prepare the Mocked Response Stream
byte [] expectedBytes = Encoding.UTF8.GetBytes(expected);
Stream responseStream = new MemoryStream();
responseStream.Write(expectedBytes, 0, expectedBytes.Length);
responseStream.Seek(0, SeekOrigin.Begin);
//Prepare the Mocked Request Stream
Stream requestStream = new MemoryStream();
requestStream.Write(expectedBytes, 0, expectedBytes.Length);
requestStream.Seek(0, SeekOrigin.Begin);
//Mock the HttpWebResponse
Mock<HttpWebResponse> response = new Mock<HttpWebResponse>();
//Set the method GetResponseStream to return the Response Stream mocked
response.Setup(c => c.GetResponseStream()).Returns(responseStream);
response.Setup(c => c.StatusCode).Returns(HttpStatusCode.OK);
//Set the method GetRequestStream to return the Request Stream mocked
Mock<HttpWebRequest> request = new Mock<HttpWebRequest>();
request.Setup(c => c.GetResponse()).Returns(response.Object);
request.Setup(c => c.GetRequestStream()).Returns(requestStream);
//Create a Object to mock the HttpWebRequest Create Method
Mock<IHttpWebRequestFactory> factory = new Mock<IHttpWebRequestFactory>();
factory.Setup(c => c.Create(It.IsAny<string>()))
.Returns(request.Object);
TestableRestClient client = new TestableRestClient();
client.HttpWebRequestFake = factory.Object.Create("http://mytest");
long actualBytes = client.PostRequest(new Uri("http://mytest"), expected);
string actual = client.responseValue;
Assert.AreEqual(expected, actual);
}
}
Not really sure what you want to achieve, but this may help. The error message tells you the exact problem and gives you a hint what to do.
If you check your code, the class WrapHttpWebRequest is not of type HttpWebRequest. However, it holds an HttpWebRequest. These two steps solve the direct issue, but you may run into another issue. First, provide a property to the class WrapHttpWebRequest:
public HttpWebRequest HttpWebRequest { get { return _request; } }
Then change you failing code line to this:
client.HttpWebRequestFake = factory.Object.Create("http://127.0.0.1").HttpWebRequest;
I reckon though that it would be better to change the class WrapHttpWebRequest and inherit from 'HttpWebRequest' like this ...
public class WrapHttpWebRequest: HttpWebRequest, IHttpWebRequest
... and change its implementation accordingly.
I have a method I am using to to work with a Json response. Since this is part of a harness and I am going to be creating a number of different data objects is it possible to make this more generic so I don't have to create same code for each different data object I create.
[DataContract]
class Stats
{
[DataMember]
public string StatusCode {get;set;}
[DataMember]
public int ProspectCount {get;set;}
[DataMember]
public int MessageCount {get;set;}
[DataMember]
public int NewListingCount {get;set;}
[DataMember]
public int ReminderCount {get;set;}
[DataMember]
public int MyListingCount {get;set;}
[DataMember]
public int OfficListingCount {get;set;}
}
public static Stats SendRequest(string requestUrl)
{
try
{
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Stats));
object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
Stats jsonResponse
= objResponse as Stats;
return jsonResponse;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
I essentially want to be able to create a second and third data contract without having to recreate the SendRequest method.
Two options:
1: Make the SendRequest method the only static method in another class and have every object that needs it call it like this:
RequestSender.SendRequest(requestUrl).
2: Make this and the other classes you have to write extend a superclass that contains the SendRequest(String requestUrl) method so that they have access to that same method via inheritance.
Would a generic method work? The signature might look like this:
public static T SendRequest<T>(string requestUrl) where T : class
In the method body you would replace Stats with T.
Usage:
Stats response = RequestSender.SendRequest<Stats>("some URL");
OtherClass anotherResponse = RequestSender.SendRequest<OtherClass>("some other URL");
I ended up utilizing Json.NET for the serialization piece. This will do everything I needed it to. So now my method looks like:
public static string ProcessRequest(string requestUrl)
{
try
{
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
string responseContents;
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
Stream responseStream = response.GetResponseStream();
using(StreamReader readStream = new StreamReader(responseStream))
{
responseContents = readStream.ReadToEnd();
}
return responseContents;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
And the serialization component in another method is a simple one liner that takes the response as a string.:
Stats results = JsonConvert.DeserializeObject<Stats>(response);
I'm working on an iOS application using Xamarin.iOS / MonoTouch and I've run across a bit of a dilemma. We're downloading quite a bit of data with our application by querying JSON-files which are then processed into models that are saved into our local sqlite-database. The problem is that the class I've written is made for specific types, and I want to be able to use the same class for fetching all JSON data into local objects.
Here is my code:
using System;
using System.IO;
using System.Net;
using Newtonsoft.Json;
using System.Collections.Generic;
#pragma warning disable 0414 // Supressing Warning CS0414:
namespace CommonLibrary {
public class JSONHandler {
// Debug Constants:
private static String DEBUG_FILE_TAG = "[JSONHandler] ";
// Define variables:
private Uri JSONRequestURL;
private bool RequestTimedOut;
private bool RequestSuccessful;
private string ResponseContent;
private List<Post> JSONObjects;
// Define objects:
private HttpWebRequest JSONWebRequest;
private HttpWebResponse JSONWebResponse;
// Constructor:
public JSONHandler(string requestURL){
// Set request URL:
this.JSONRequestURL = new Uri(requestURL);
// Set default statuses:
this.RequestTimedOut = false;
this.RequestSuccessful = false;
}
// Create web request:
private void CreateWebRequest(){
this.JSONWebRequest = (HttpWebRequest) WebRequest.Create (this.JSONRequestURL);
this.JSONWebRequest.Method = "GET";
this.JSONWebRequest.Timeout = 5000;
this.JSONWebRequest.KeepAlive = false;
this.JSONWebRequest.AllowAutoRedirect = false;
this.JSONWebRequest.ContentType = "application/json";
}
// Get request response:
private void GetRequestResponse(){
try {
// Catch the response:
this.JSONWebResponse = (HttpWebResponse) this.JSONWebRequest.GetResponse ();
// Check the status code:
if (this.JSONWebResponse.StatusCode == HttpStatusCode.OK){
// Get content:
StreamReader reader = new StreamReader (this.JSONWebResponse.GetResponseStream ());
this.ResponseContent = reader.ReadToEnd();
// Close response:
this.JSONWebResponse.Close();
// Check response length:
if (!String.IsNullOrWhiteSpace(this.ResponseContent)){
this.JSONObjects = JsonConvert.DeserializeObject<List<Post>>(this.ResponseContent);
this.RequestSuccessful = true;
} else {
this.RequestSuccessful = false;
}
} else {
this.RequestSuccessful = false;
}
} catch (WebException){
this.RequestTimedOut = true;
this.RequestSuccessful = false;
} catch (TimeoutException){
this.RequestTimedOut = true;
this.RequestSuccessful = false;
}
}
// Fetch JSON from server:
public void FetchJSON(){
this.CreateWebRequest ();
this.GetRequestResponse ();
}
// Return request status:
public bool RequestWasSuccessful(){
return RequestSuccessful;
}
// Return timeout status:
public bool RequestDidTimeOut(){
return RequestTimedOut;
}
// Get object count:
public int GetJSONCount(){
return this.JSONObjects.Count;
}
// Get list of objects:
public List<Post> GetJSONObjects (){
return this.JSONObjects;
}
}
}
As you can see, I have to change the type that are stored in the lists from Post to any other object and create a new file, for instance, JSONPost, JSONRunner, JSONLayer etc, and I'd like to handle that with just one class, JSONHandler. Hopefully someone here can help me with this matter. I'm going to have the following classes now:
Post
Layer
RelayTeam
RelayRunner
RelayRunnerResult
MarathonRunner
MarathonRunnerResult
And as you all can understand it won't be good having a duplicated file just for all of these.
I'm really thankful for any help I can get!
Best regards,
Jonathan
Use Generics - if the type of the JSONObjects collection is the only thing that varies, you can do this
public class JSONHandler<T> {
...
private List<T> JSONObjects;
When you create a new JSONHandler instance, you can specify the type
var handler = new JSONHandler<Post>();
var handler = new JSONHandler<Layer>();
var handler = new JSONHandler<RelayTeam>();
I'm using Moq to mock HttpWebResponse for unit testing. I created a mock class that inherits from the class I'm trying to test and I'm overriding the method that returns the HttpWebResponse. I want to write a JSON string to the response stream from the unit test but I get an ArgumentException when trying to read the stream saying "Stream was not readable".
Here is what I have:
public class ParentClass
{
private string ProcessResponse(HttpWebResponse response)
{
string json = String.Empty;
using (var streamReader = new StreamReader(response.GetResponseStream())) //exception here
{
json = streamReader.ReadToEnd();
}
return json;
}
//other stuff
}
public class MockClass : ParentClass
{
public Stream responseStream = new MemoryStream();
public void WriteJson(string json)
{
using(var writer = new StreamWriter(responseStream))
{
writer.Write(json);
}
}
protected override HttpWebResponse GetResponse(HttpWebRequest request)
{
var response = new Mock<HttpWebResponse>();
response.Setup(r => r.GetResponseStream()).Returns(responseStream);
return response.Object;
}
}
The problem seemed to be with the using statement. Here are the changes I made:
public void WriteJson(string json)
{
var jsonBytes = Encoding.UTF8.GetBytes(json);
responseStream.Write(jsonBytes, 0, jsonBytes.Length);
responseStream.Seek(0, SeekOrigin.Begin);
}
It's safer to use an overload of StreamWriter which leaves the underlying stream open:
public StreamWriter(Stream stream, Encoding encoding, int bufferSize, bool leaveOpen)