I'm using OWIN with WebAPI integration as WebApp. Future plan is to use OWIN self-hosting which is working fine but the OWIN testserver implementation is not working together with RestSharp:
Sample without RestSharp:
https://blogs.msdn.microsoft.com/webdev/2013/11/26/unit-testing-owin-applications-using-testserver/
First attempt is to use a mock class derived from RestClient class:
public class MockRestClient : RestClient
{
public TestServer TestServer { get; set; }
public MockRestClient(TestServer testServer)
{
TestServer = testServer;
}
public override IRestResponse Execute(IRestRequest request)
{
// TODO: Currently the test server is only doing GET requests via RestSharp
var response = TestServer.HttpClient.GetAsync(request.Resource).Result;
var restResponse = ConvertToRestResponse(request, response);
return restResponse;
}
private static RestResponse ConvertToRestResponse(IRestRequest request, HttpResponseMessage httpResponse)
{
RestResponse restResponse1 = new RestResponse();
restResponse1.Content = httpResponse.Content.ReadAsStringAsync().Result;
restResponse1.ContentEncoding = httpResponse.Content.Headers.ContentEncoding.FirstOrDefault();
restResponse1.ContentLength = (long)httpResponse.Content.Headers.ContentLength;
restResponse1.ContentType = httpResponse.Content.Headers.ContentType.ToString();
if (httpResponse.IsSuccessStatusCode == false)
{
restResponse1.ErrorException = new HttpRequestException();
restResponse1.ErrorMessage = httpResponse.Content.ToString();
restResponse1.ResponseStatus = ResponseStatus.Error;
}
restResponse1.RawBytes = httpResponse.Content.ReadAsByteArrayAsync().Result;
restResponse1.ResponseUri = httpResponse.Headers.Location;
restResponse1.Server = "http://localhost";
restResponse1.StatusCode = httpResponse.StatusCode;
restResponse1.StatusDescription = httpResponse.ReasonPhrase;
restResponse1.Request = request;
RestResponse restResponse2 = restResponse1;
foreach (var httpHeader in httpResponse.Headers)
restResponse2.Headers.Add(new Parameter()
{
Name = httpHeader.Key,
Value = (object)httpHeader.Value,
Type = ParameterType.HttpHeader
});
//foreach (var httpCookie in httpResponse.Content.)
// restResponse2.Cookies.Add(new RestResponseCookie()
// {
// Comment = httpCookie.Comment,
// CommentUri = httpCookie.CommentUri,
// Discard = httpCookie.Discard,
// Domain = httpCookie.Domain,
// Expired = httpCookie.Expired,
// Expires = httpCookie.Expires,
// HttpOnly = httpCookie.HttpOnly,
// Name = httpCookie.Name,
// Path = httpCookie.Path,
// Port = httpCookie.Port,
// Secure = httpCookie.Secure,
// TimeStamp = httpCookie.TimeStamp,
// Value = httpCookie.Value,
// Version = httpCookie.Version
// });
return restResponse2;
}
Unfortunatly I stuck with Post events, which needs html body from restResponse.
Has anybody done something similar.
BTW: I can also use OWIN unit tests with self-hosting OWIN, but this will not work on Teamcity automatic builds.
I changed the mock rest Client to work with Post/Put/Delete methods too. It is not 100% complete (missing auth, Cookies, files etc.), but in my case it is sufficient:
public class MockRestClient : RestClient
{
public TestServer TestServer { get; set; }
public MockRestClient(TestServer testServer)
{
TestServer = testServer;
}
public override IRestResponse Execute(IRestRequest request)
{
// TODO: Currently the test server is only doing GET requests via RestSharp
HttpResponseMessage response = null;
Parameter body = request.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
HttpContent content;
if (body != null)
{
object val = body.Value;
byte[] requestBodyBytes;
string requestBody;
if (val is byte[])
{
requestBodyBytes = (byte[]) val;
content = new ByteArrayContent(requestBodyBytes);
}
else
{
requestBody = Convert.ToString(body.Value);
content = new StringContent(requestBody);
}
}
else
content = new StringContent("");
string urladd = "";
IEnumerable<string> #params = from p in request.Parameters
where p.Type == ParameterType.GetOrPost && p.Value != null
select p.Name + "=" + p.Value;
if(!#params.IsNullOrEmpty())
urladd = "?" + String.Join("&", #params);
IEnumerable<HttpHeader> headers = from p in request.Parameters
where p.Type == ParameterType.HttpHeader
select new HttpHeader
{
Name = p.Name,
Value = Convert.ToString(p.Value)
};
foreach (HttpHeader header in headers)
{
content.Headers.Add(header.Name, header.Value);
}
content.Headers.ContentType.MediaType = "application/json";
switch (request.Method)
{
case Method.GET:
response = TestServer.HttpClient.GetAsync(request.Resource + urladd).Result;
break;
case Method.DELETE:
response = TestServer.HttpClient.DeleteAsync(request.Resource + urladd).Result;
break;
case Method.POST:
response = TestServer.HttpClient.PostAsync(request.Resource + urladd, content).Result;
break;
case Method.PUT:
response = TestServer.HttpClient.PutAsync(request.Resource + urladd, content).Result;
break;
default:
return null;
}
var restResponse = ConvertToRestResponse(request, response);
return restResponse;
}
private static RestResponse ConvertToRestResponse(IRestRequest request, HttpResponseMessage httpResponse)
{
RestResponse restResponse1 = new RestResponse();
restResponse1.Content = httpResponse.Content.ReadAsStringAsync().Result;
restResponse1.ContentEncoding = httpResponse.Content.Headers.ContentEncoding.FirstOrDefault();
restResponse1.ContentLength = (long)httpResponse.Content.Headers.ContentLength;
restResponse1.ContentType = httpResponse.Content.Headers.ContentType.ToString();
if (httpResponse.IsSuccessStatusCode == false)
{
restResponse1.ErrorException = new HttpRequestException();
restResponse1.ErrorMessage = httpResponse.Content.ToString();
restResponse1.ResponseStatus = ResponseStatus.Error;
}
restResponse1.RawBytes = httpResponse.Content.ReadAsByteArrayAsync().Result;
restResponse1.ResponseUri = httpResponse.Headers.Location;
restResponse1.Server = "http://localhost";
restResponse1.StatusCode = httpResponse.StatusCode;
restResponse1.StatusDescription = httpResponse.ReasonPhrase;
restResponse1.Request = request;
RestResponse restResponse2 = restResponse1;
foreach (var httpHeader in httpResponse.Headers)
restResponse2.Headers.Add(new Parameter()
{
Name = httpHeader.Key,
Value = (object)httpHeader.Value,
Type = ParameterType.HttpHeader
});
//foreach (var httpCookie in httpResponse.Content.)
// restResponse2.Cookies.Add(new RestResponseCookie()
// {
// Comment = httpCookie.Comment,
// CommentUri = httpCookie.CommentUri,
// Discard = httpCookie.Discard,
// Domain = httpCookie.Domain,
// Expired = httpCookie.Expired,
// Expires = httpCookie.Expires,
// HttpOnly = httpCookie.HttpOnly,
// Name = httpCookie.Name,
// Path = httpCookie.Path,
// Port = httpCookie.Port,
// Secure = httpCookie.Secure,
// TimeStamp = httpCookie.TimeStamp,
// Value = httpCookie.Value,
// Version = httpCookie.Version
// });
return restResponse2;
}
Related
I'm trying to achieve update contact with Xero api: I'm trying to update AccountNumber value is null.
This is the code for update method. I'm passing value with ContactId and AccountNumber.
var xContact = new XeroContact
{
AccountNumber = null,
ContactId = CustomerGUID
};
var request = new XeroContactRequest { AuthToken = _authHelper.AccessToken, Search = "", TenantId = _authHelper.TenantId, CustomerGUID = CustomerGUID, Contact = xContact };
var xeroCustomerResult = _xeroContactBusiness.UpdateContact(request);
update function:
public IResult<XeroContact> UpdateContact(XeroContactRequest data)
{
var result = new Result<XeroContact>();
try
{
if (data == null || string.IsNullOrEmpty(data.AuthToken) || string.IsNullOrEmpty(data.TenantId)) throw new ArgumentNullException("data is required");
var client = new RestClient(BaseUrl);
var method = string.Format("/{0}/{1}", _apiMethod, data.CustomerGUID);
var request = new RestRequest(method, Method.POST);
request.AddHeader("Authorization", string.Format("Bearer {0}", data.AuthToken));
request.AddHeader("Accept", "application/json");
request.AddHeader("Xero-tenant-id", data.TenantId);
var postData = JsonConvert.SerializeObject(data.Contact);
request.AddJsonBody(postData);
var response = client.Execute(request);
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception(ParseError(response.Content));
}
}
catch (Exception ex)
{
result.HasData = false;
result.Data = null;
result.Error = ex;
}
return result;
}
Can you please help me understand what I'm doing wrong? How can i update AccountNumber by ContactId. Thanks !
I have resolved this issue below way, Just need to send ContactId and those parameter that's need to be updated. Here "AccountNumber" field need to be updated. Thanks !
var body = new
{
ContactId = data.CustomerGUID,
AccountNumber=""
};
var postData = JsonConvert.SerializeObject(body);
request.AddJsonBody(postData);
I'm getting absolutely insane with this, I've tried almost everything and can't find a way to pass a string value from a service to backend to return Json result based on that string.
Here's the problem, I have a backend that cooks all the JSON with meta-info that
frontend provides, and then return them to the frontend to display, on this case I have to get a JSON that's based on a filter that is made by a string inserted in frontend but can't find a way to pass the string to the backend, and I don't want to pass it through the URL.
Here's my code:
angular typescript service: I want to pass the "whr"
getAdvancedFilterResult(concept: string, whr: string): Promise<any> {
const headers: Headers = new Headers({
'Content-Type': 'application/json'
});
this.authService.getAuthorizationHeader(headers);
headers.append('IdLng', this.config.idLanguage);
const options: RequestOptions = new RequestOptions();
options.headers = headers;
return this.http.get(this.config.apiDomain + this.config.apiEndpointEntities + '/' + concept + '/' + "filtered",
options
)
.toPromise()
.then(
response => response.json() as any[]
)
.catch((error) => this.customHandleError(error, this.toastrService));
}
Backend controller:
[Route("api/Entities/{entity}/filtered/")]
public HttpResponseMessage GetFilter(string entity) {
HttpResponseMessage response = new HttpResponseMessage();
string action = "READ";
//Check Authorization
AuthorizationResponse authResponse = AuthProvider.CheckAuthorization(new AuthorizationRequest() {
SCode = UserUtils.GetUserSCode(User),
ConceptString = entity,
ActionString = action,
UserId = UserUtils.GetUserID(User),
ExtraParameters = new AuthorizationRequest.ExtraParamaters() {
IdsOnly = false, Where = "!!!!!WHR HERE!!!!"
}
});
if (authResponse.IsAuthorized) {
//code
response = Request.CreateResponse(HttpStatusCode.OK, json);
} else {
response = Request.CreateResponse(HttpStatusCode.Unauthorized);
}
return response;
}
Should I pass it through the header, with headers.append('whr', whr);, that goes into the options on http.get or into body with options.body = whr;?
Also, how can I get it on the backend side to use?
You should pass the Headers like this:
getAdvancedFilterResult(concept: string, whr: string): Promise<any> {
this.authService.getAuthorizationHeader(headers);
let headers: HttpHeaders = new HttpHeaders();
headers = headers.append('Content-Type', 'application/json');
headers = headers.append('x-corralation-id', '12345');
headers = headers.append('IdLng', this.config.idLanguage);
headers = headers.append('whr', whr);
const options: RequestOptions = new RequestOptions();
options.headers = headers;
return this.http.get(this.config.apiDomain + this.config.apiEndpointEntities + '/' + concept + '/' + "filtered",
options
)
.toPromise()
.then(
response => response.json() as any[]
)
.catch((error) => this.customHandleError(error, this.toastrService));
}
To get the headers on the Server Side try this:
[Route("api/Entities/{entity}/filtered/")]
public HttpResponseMessage GetFilter(string entity) {
var request = Request;
var headers = response.Headers;
HttpResponseMessage response = new HttpResponseMessage();
string action = "READ";
var whrHeader = headers.Contains("whr") ? request.Headers.GetValues("whr").First() : ""
AuthorizationResponse authResponse = AuthProvider.CheckAuthorization(new AuthorizationRequest() {
SCode = UserUtils.GetUserSCode(User),
ConceptString = entity,
ActionString = action,
UserId = UserUtils.GetUserID(User),
ExtraParameters = new AuthorizationRequest.ExtraParamaters() {
IdsOnly = false,
Where = whrHeader
}
});
if (authResponse.IsAuthorized) {
//code
response = Request.CreateResponse(HttpStatusCode.OK, json);
} else {
response = Request.CreateResponse(HttpStatusCode.Unauthorized);
}
return response;
}
I got the solution, thanks to SiddAjmera!!
At frontend service:
getAdvancedFilterResult(concept: string, whr: string): Promise<any> {
let headers: Headers = new Headers();
this.authService.getAuthorizationHeader(headers);
headers.append('Content-Type', 'application/json');
headers.append('IdLng', this.config.idLanguage);
headers.append('whr', whr);
const options: RequestOptions = new RequestOptions();
options.headers = headers;
return this.http.get(
this.config.apiDomain + this.config.apiEndpointEntities + '/' + concept + '/' + "filtered",
options
)
.toPromise()
.then(
response => response.json() as any[]
)
.catch((error) => this.customHandleError(error, this.toastrService));
}
And then on the backend, just used the UserUtils already made to get the header which has the value 'whr' and pass it through a function.
UserUtilis.cs:
public static string Where(HttpRequestMessage re) {
string whereCLause = "";
var headers = re.Headers;
if (headers.Contains("whr")) {
whereCLause = headers.GetValues("whr").First();
} else {
whereCLause = " ";
}
return whereCLause;
}
And Controller.cs
...
var re = Request;
HttpResponseMessage response = new HttpResponseMessage();
string action = "READ";
//Check Authorization
AuthorizationResponse authResponse = AuthProvider.CheckAuthorization(new AuthorizationRequest() {
SCode = UserUtils.GetUserSCode(User),
ConceptString = entity,
ActionString = action,
UserId = UserUtils.GetUserID(User),
ExtraParameters = new AuthorizationRequest.ExtraParamaters() {
IdsOnly = false, Where = UserUtils.Where(re)
}
});
...
I have trained dialogflow but i want to create an webhook API for receiving and sending an response.
I have created the intent with Enabled the webhook to get response in it.
Any help would be appreciated.....
[HttpPost]
public dynamic DialogAction([FromBody] WebhookRequest dialogflowRequest)
{
var intentName = dialogflowRequest.QueryResult.Intent.DisplayName;
var actualQuestion = dialogflowRequest.QueryResult.QueryText;
var testAnswer = $"Dialogflow Request for intent {intentName} and question {actualQuestion}";
var parameters = dialogflowRequest.QueryResult.Parameters;
var dialogflowResponse = new WebhookResponse
{
FulfillmentText = testAnswer,
FulfillmentMessages =
{ new Intent.Types.Message
{ SimpleResponses = new Intent.Types.Message.Types.SimpleResponses
{ SimpleResponses_ =
{ new Intent.Types.Message.Types.SimpleResponse
{
DisplayText = testAnswer,
TextToSpeech = testAnswer,
}
}
}
}
}
};
var jsonResponse = dialogflowResponse.ToString();
return new ContentResult { Content = jsonResponse, ContentType = "application/json" }; ;
//return "Connecteds";
}
I want to create a unit test method for the below method which is receiving a file upload "text file" data and parsing it, I tried to use Moq and created a method but I am still very confused in the concept, I need a sample code, I've read many stackover flow questions but it is all for Controllers not Web API
the method used
// Enable both Get and Post so that our jquery call can send data, and get a status
[HttpGet]
[HttpPost]
public HttpResponseMessage Upload()
{
// Get a reference to the file that our jQuery sent. Even if multiple files, they will
// all be their own request and be the 0 index
if (HttpContext.Current.Request.Files.Count>0)
{
HttpPostedFile file = HttpContext.Current.Request.Files[0];
if (file != null && file.ContentLength > 0)
{
try
{
var extension = Path.GetExtension(file.FileName);
if (!IsFileFormatSupported(extension))
{
var objectSerialized = SerializeData(GetError( GlobalResources.NotSupportedFileExtension));
return BadResponse(objectSerialized);
}
var path = SaveFileGetPath(file);
var result = GetPaySlips(path);
var SerializedData = SerializeData(result);
return OkResponse(SerializedData);
}
catch (System.Exception exception)
{
var SerializedData = SerializeData(GetError( GlobalResources.CouldNotReadFile + " " + exception.Message));
return BadResponse(SerializedData);
}
}
else
{
var SerializedData = SerializeData(GetError(file.FileName + " " + GlobalResources.FileisCorrupt));
return BadResponse(SerializedData);
}
}else
{
var SerializedData = SerializeData(GetError( GlobalResources.FileisCorrupt));
return BadResponse(SerializedData);
}
}
the code I did so far
var FileUploadCtrl = new UploadController();
Mock<HttpRequestMessage> cc = new Mock<HttpRequestMessage>();
UTF8Encoding enc = new UTF8Encoding();
// Mock<HttpPostedFileBase> file1 = new Mock<HttpPostedFileBase>();
//file1.Expect(f=>f.InputStream).Returns(file1.Object.InputStream);
//cc.Expect(ctx => ctx.Content).Returns(new retur);
// cc.Expect(ctx => ctx.Content).Returns();
var content = new ByteArrayContent( /* bytes in the file */ );
content.Headers.Add("Content-Disposition", "form-data");
var controllerContext = new HttpControllerContext
{
Request = new HttpRequestMessage
{
Content = new MultipartContent { content }
}
};
//file1.Expect(d => d.FileName).Returns("FileTest.csv");
//file1.Expect(d => d.InputStream).Returns(new HttpResponseMessage(HttpStatusCode.OK)));
var config = new HttpConfiguration();
//var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/upload");
var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "FileUpload" } });
FileUploadCtrl.ControllerContext = new HttpControllerContext(config, routeData, cc.Object);
var r = FileUploadCtrl.Upload();
Assert.IsInstanceOfType(r, typeof(HttpResponseMessage));
I am trying to access the Jira rest API via C#. For that I am using the Windows.Web.Http.HttpClient. But all I get as a return value is HTML.
I am calling the following URL: https://jira.atlassian.com/rest/api/latest/field/
Little Edit
When I call the url from a browser it works fine, just the call from the HttpClient doesn't work.
Here is my code:
public async Task<IRestResponse> Execute(RestRequest request) {
var restResponse = new RestResponse();
var client = new HttpClient();
var req = new HttpRequestMessage(request.Method, new Uri(BaseUrl, UriKind.RelativeOrAbsolute));
foreach (var item in request.headers) {
req.Headers[item.Key] = item.Value;
}
req.Headers.Accept.Add(new HttpMediaTypeWithQualityHeaderValue("application/json"));
if (this.Authenticator != null)
req.Headers["Authorization"] = this.Authenticator.GetHeader();
var res = await client.SendRequestAsync(req);
restResponse.Content = await res.Content.ReadAsStringAsync();
restResponse.StatusCode = res.StatusCode;
restResponse.StatusDescription = res.ReasonPhrase;
if (!res.IsSuccessStatusCode) {
restResponse.ErrorMessage = restResponse.Content;
restResponse.ResponseStatus = ResponseStatus.Error;
} else if (res.StatusCode == HttpStatusCode.RequestTimeout) {
restResponse.ResponseStatus = ResponseStatus.TimedOut;
} else if (res.StatusCode == HttpStatusCode.None) {
restResponse.ResponseStatus = ResponseStatus.None;
} else {
restResponse.ResponseStatus = ResponseStatus.Completed;
}
return restResponse;
}
I just found my problem, I don't add the relative path anywhere. It just calls the BaseUrl meaning https://jira.atlassian.com/ that explains why I get the HTML page.