Web Api Service - asp.net-mvc-4

I am Consuming web api service from one project (project1) to another project (project2) but when i try to get the response from project2 to project1 with this code
using (var client = new WebClient())
{
string json = URL;
Var jdownload = client.DownloadString(json);
}
It's adding back slashed into "jdownload" Var please guide me how i can get that response without that backslashes
i.e
“servicefor” = “GetData”,
“settings” = {
\"stringname\":5,
\"url\":\"null",
\"services\":\"GetSet\",
\"interval\":2.0,
\"alldatacontains\":200,
\"netamountname\":\"BulkFetch\"
}

I got the solution how can i get the Clean Jason
public JObject GetData(string dataO)
{
var data = MethodToGetData(dataO);
JObject pobj = JObject.FromObject(new
{
type = "stgdats",
val = "val",
d_id = id,
sat = data
}
);
return pobj;
}

Related

HttpClient not sending post data to NancyFX endpoint

I am doing some integration testing of my web API that uses NancyFX end points. I have the xUnit test create a test server for the integration test
private readonly TestServer _server;
private readonly HttpClient _client;
public EventsModule_Int_Tester()
{
//Server setup
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_server.AllowSynchronousIO = true;//Needs to be overriden in net core 3.1
_client = _server.CreateClient();
}
Inside a Test Method I tried the following
[Fact]
public async Task EventTest()
{
// Arrange
HttpResponseMessage expectedRespone = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
var data = _server.Services.GetService(typeof(GenijalnoContext)) as GenijalnoContext;
//Get come random data from the DBcontext
Random r = new Random();
List<Resident> residents = data.Residents.ToList();
Resident random_residnet = residents[r.Next(residents.Count)];
List<Apartment> apartments = data.Apartments.ToList();
Apartment random_Apartment = apartments[r.Next(apartments.Count)];
EventModel model = new EventModel()
{
ResidentId = random_residnet.Id,
ApartmentNumber = random_Apartment.Id
};
//Doesnt work
IList<KeyValuePair<string, string>> nameValueCollection = new List<KeyValuePair<string, string>> {
{ new KeyValuePair<string, string>("ResidentId", model.ResidentId.ToString()) },
{ new KeyValuePair<string, string>("ApartmentNumber", model.ApartmentNumber.ToString())}
};
var result = await _client.PostAsync("/Events/ResidentEnter", new FormUrlEncodedContent(nameValueCollection));
//Also Doesnt work
string json = JsonConvert.SerializeObject(model, Formatting.Indented);
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _client.PostAsync("/Events/ResidentEnter", httpContent);
//PostAsJsonAsync also doesnt work
// Assert
Assert.Equal(response.StatusCode, expectedRespone.StatusCode);
}
The NancyFX module does trigger the endpoint and receives the request but without the body
What am I doing wrong? Note that the NancyFX endpoint has no issue transforming a Postman call into a valid model.
The NancyFX endpoint
Alright I fixed it, for those curious the issue was that the NancyFX body reader sometimes does not properly start reading the request body. That is that the stream reading position isn't 0 (the start) all the time.
To fix this you need to create a CustomBoostrapper and then override the ApplicationStartup function so you can set up a before request pipeline that sets the body position at 0
Code below
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
pipelines.BeforeRequest.AddItemToStartOfPipeline(ctx =>
{
ctx.Request.Body.Position = 0;
return null;
});
}

Simple serialize ODataQueryOptions

I'm trying to:
[EnableQuery]
[HttpGet]
[ODataRoute("")]
public IHttpActionResult Get(ODataQueryOptions<UserODataModel> options)
{
var users = _repository.RetrieveOData();
var serialQuery = JsonConvert.SerializeObject(options, jsonOptions);
//save serialQuery somewhere
return Ok(users);
}
But got
Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'ReadTimeout' on 'Microsoft.Owin.Host.SystemWeb.CallStreams.InputStream'.'
"Timeouts are not supported on this stream."
I know there is already a question about serialize Stream:
Newtonsoft Json.net - how to serialize content of a stream?
But in this case i can't "extract stream value" from ODataQueryOptions, or can I?
Some ideia?
Since we work on the same company, if anyone is interested, we found a way, maybe not the pretty way, to serialize an ODataQueryOptions:
public static ODataQueryOptions DeserializeQueryOptions(SerializedQueryOptions options)
{
var uri = new Uri(teste.OriginalUri);
var model = ODataConfig.Model; //GetEdmModel
var segment = model.EntityContainer.FindEntitySet(options.EdmType);
var newPath = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(segment));
var httpConfiguration = new HttpConfiguration();
httpConfiguration.EnableDependencyInjection();
var request = new HttpRequestMessage(HttpMethod.Get, uri)
{
Properties =
{
{ HttpPropertyKeys.HttpConfigurationKey, httpConfiguration },
}
};
var context = new ODataQueryContext(model, options.EntityType, newPath);
var oDataQueryOptions = new ODataQueryOptions(context, request);
return oDataQueryOptions;
}
public static SerializedQueryOptions SerializeQueryOptions(ODataQueryOptions options)
{
return new SerializedQueryOptions
{
OriginalUri = options.Request.RequestUri.AbsoluteUri,
EdmType = options.Context.NavigationSource.Name,
EntityType = options.Context.ElementClrType
};
}
After you serialize it to an object you can serialize it to a JSON string:
var queryOptionsSerialized = new SerializedQueryOptions()
{
OriginalUri = "http://localhost:25723/odata/users?$skip=0&$top=2&$orderby=fullName&$count=true",
EdmType = "users",
EntityType = typeof(UserODataModel)
};
var json = JsonConvert.SerializeObject(queryOptionsSerialized);
var deserialized = JsonConvert.DeserializeObject<SerializedQueryOptions>(json);
var options = ODataQueryOptionsHelper.DeserializeQueryOptions(deserialized);
In case One is not using OData routing or using an ApiController (not ODataController),
modify the way of Obtaining ODataPath to:
ODataUriParser parser = new ODataUriParser(model, serviceRoot, requestUri);
ODataPath path = parser.ParsePath();
//var newPath = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(segment));
Microsoft.AspNet.OData.Routing.ODataPath newPath = new Microsoft.AspNet.OData.Routing.ODataPath(path.FirstOrDefault());
where the serviceRoot is the Url part other that the path defined in the model.

How to use the continuationtoken in TFS 2015 Object Model: GetBuildsAsync?

I am using the following code
BuildHttpClient service = new BuildHttpClient(tfsCollectionUri,
new Microsoft.VisualStudio.Services.Common.VssCredentials(true));
var asyncResult = service.GetBuildsAsync(project: tfsTeamProject);
var queryResult = asyncResult.Result;
This returns only the first 199 builds.
Looks like in need to use the continuationtoken but am not sure how to do this. The docs say that the REST API will return the token. I am using the Object Model, and am looking for how to retrieve the token!
I am using Microsoft.TeamFoundationServer.Client v 14.102.0; Microsoft.TeamFoundationServer.ExtendedClient v 14.102.0, Microsoft.VisualStudio.Service.Client v 14.102.0 and Microsoft.VisualStudio.Services.InteractiveClient v 14.102.0
Question
How do I use the continuation token **when using the TFS Object model?
The continuationToken is in the response header after the first call to the API:
x-ms-continuationtoken: xxxx
It can not be retrieved from .net client library. You have to use the rest api to retrieve the header information. Here is an example for your reference:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace GetBuilds
{
class Program
{
public static void Main()
{
Task t = GetBuilds();
Task.WaitAll(new Task[] { t });
}
private static async Task GetBuilds()
{
try
{
var username = "xxxxx";
var password = "******";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
using (HttpResponseMessage response = client.GetAsync(
"http://tfs2015:8080/tfs/DefaultCollection/teamproject/_apis/build/builds?api-version=2.2").Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
You have to use 'GetBuildsAsync2', which returns an IPagedList. You can retrieve the ContinuationToken from the IPagedList:
// Iterate to get the full set of builds
string continuationToken = null;
List<Build> builds = new List<Build>();
do
{
IPagedList<Build> buildsPage = service.GetBuildsAsync2(tfsTeamProject, continuationToken: continuationToken).Result;
//add the builds
builds.AddRange(buildsPage);
//get the continuationToken for the next loop
continuationToken = buildsPage.ContinuationToken;
}
while (continuationToken != null);

How to implement the await keyword?

I have written a code to get the projects from the TFS 2013 server using the tfs web api. As the methord is taking too long to execute i.e like 1.5 minutes, so i wanted to make this methord as async. So i added the async and task in the return type. When i see in visual studio is shows a message that the methord does not have await keyword. where should i add the await keyword. I am very new to async programming.
public override async Task<List<Project>> GetProjects()
{
List<Project> retunResult = new List<Project>();
using (var http = new HttpClient(GetHttpHandler()))
{
var response = http.GetAsync(_baseUrl + "_apis/projectCollections?" + tfsWebApiVersionSring).Result;
if (response.IsSuccessStatusCode)
{
response.EnsureSuccessStatusCode();
TFS2013TeamProjectCollection.Rootobject obj = JsonConvert.DeserializeObject<TFS2013TeamProjectCollection.Rootobject>(response.Content.ReadAsStringAsync().Result);
if (obj != null)
{
foreach (TFS2013TeamProjectCollection.Value projColl in obj.value)
{
if (projColl.state == "Started")
{
var responseProj = http.GetAsync(_baseUrl + projColl.name + "/_apis/projects?" + tfsWebApiVersionSring).Result;
if (responseProj.IsSuccessStatusCode)
{
responseProj.EnsureSuccessStatusCode();
TFS2013TeamProject.Rootobject obj1 = JsonConvert.DeserializeObject<TFS2013TeamProject.Rootobject>(responseProj.Content.ReadAsStringAsync().Result);
if (obj1 != null)
{
Project p;
foreach (TFS2013TeamProject.Value TeamProj in obj1.value)
{
p = new Project();
p.collectionName = TeamProj.collection.name;
p.description = TeamProj.description;
p.id = TeamProj.id;
p.name = TeamProj.name;
p.collectionName = TeamProj.collection.name;
p.url = TeamProj.url;
retunResult.Add(p);
}
}
}
}
}
return retunResult;
}
}
}
return null;
}
You could refer to this code snippet about using TFS REST API to get something in async way.
public static async void RESTAPIMethod()
{
HttpClientHandler authtHandler = new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials
};
using (HttpClient client = new HttpClient(authtHandler))
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
using (HttpResponseMessage response = client.GetAsync(
"Put the REST API URL here").Result)
{
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
}
}
}
Another method about using TFS REST API:
You could also install this Nuget package for your project. Then using these assemblies in this package to run a REST API with C#. This is different with the method above, it's much more convenient. Here is an example about get a build information using Microsoft.TeamFoundation.Build.WebApi assembly in Async method.
Example:
What object returns from TFS2015 RestAPI
You shouldn't use Result at all. Every place in your code where you have:
var resp = http.GetAsync(url).Result;
you should have:
var resp = await http.GetAsync(url);

How can I provide Metadata from my WCF service for consumption in Breeze

I am trying to adapt an existing WebApi/MVC4 app to use Breeze lookups.
Currently I retrieve my DTOs via
[HttpGet]
public IQueryable<ThingDto> GetThings()
{
var channelFactory = ThingServiceConfiguration.CreateChannelFactory();
_serviceFactory = () => new WcfProxy<IThingService>(channelFactory.CreateChannel());
var client = _serviceFactory();
IQueryable<ThingDto> result = client.Execute(p => p.GetThings()).OrderBy(x => x.Name).AsQueryable();
return result;
}
I'm not sure how I implement this method Metadata()
public string Metadata()
{
//normally something like this if using a EF DataContext
// return _someContextProvider.Context.Things;
}
How I setup the WCF config
public class ThingServiceConfiguration
{
const string AppSettingKey = "ThingServiceUrl";
public static ChannelFactory<IThingService> CreateChannelFactory()
{
// var serviceUrl = ConfigurationManager.AppSettings[AppSettingKey];
var serviceUrl = "http://localhost:86/ThingService.svc";
var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
{
MaxReceivedMessageSize = 200000000,
SendTimeout = TimeSpan.FromMinutes(2),
ReceiveTimeout = TimeSpan.FromMinutes(2)
};
var address = new EndpointAddress(serviceUrl);
return new ChannelFactory<IThingService>(binding, address);
}
}
Could this metadata be provided with the WCF call into the Metadata() property (by providing arguments through BasicHttpBinding ?
Many thanks!
You can return Breeze 'native' metadata simply by returning the metadata in json form. Something like this:
[HttpGet]
public String Metadata() {
var folder = Path.Combine(HttpRuntime.AppDomainAppPath, "App_Data");
// metadata.json is the name of a file containing your metadata - pick any file name you like.
var fileName = Path.Combine(folder, "metadata.json");
var jsonMetadata = File.ReadAllText(fileName);
return jsonMetadata;
}
where the syntax of the metadata file is described here: Breeze metadata format.