Can anyone point me to a working example of how to POST JSON to a RESTful API (e.g. Web API) using Windows Phone 8? I have a working example for GET but can't seem to find any working examples for POST. All of the POST examples I've found for C# don't work on Windows Phone 8 (due to the stripped down .NET framework).
Ok, I was finally able to come up with a working solution so I wanted to post it back for completeness. However, if anyone knows of a better way to do this in Windows Phone 8, I'd love to see it!
public void SendPost(Uri uri, string json)
{
var webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
webClient.UploadStringCompleted += this.sendPostCompleted;
webClient.UploadStringAsync(uri, "POST", json);
}
private void sendPostCompleted(object sender, UploadStringCompletedEventArgs e)
{
// Handle result
Console.WriteLine("HTTP POST Result: {0}", e.Result);
}
The best way to do that would be to use Restsharp:
Dim client As New RestSharp.RestClient("https://stuff.com/api/")
Dim req As New RestSharp.RestRequest("dothings", Method.POST)
req.RequestFormat = DataFormat.Json
req.AddBody(New reqAuth With {.param1 = "stuff1", .param2= "stuff2"})
client.ExecuteAsync(req, Sub(res)
Console.WriteLine(res.Content)
End Sub)
string email = txtEmailAddress.Text;
string password = txtPassword.Text;
string confirmPassword = txtConfirmPassword.Text;
string dd = txtDD.Text;
string mm = txtMM.Text;
string yyyy = txtYYYY.Text;
UserDetails ud = new UserDetails
{
DateofBirth = DateTime.Now.ToString(),
EmailAddress=email,
Password=password,
ProfileImage="",
UserID="0"
};
WebClient wc = new WebClient();
wc.Headers["Content-Type"] = "application/json";
MemoryStream ms = new MemoryStream();
DataContractJsonSerializer serializertoUpload = new DataContractJsonSerializer(typeof(UserDetails));
serializertoUpload.WriteObject(ms, ud);
string data = Encoding.UTF8.GetString(ms.ToArray(), 0, (int)ms.Length);
wc.UploadStringAsync(new Uri("<wcfserviceurl>"), "POST", data);
Here is the definition of UserDetails class
public class UserDetails
{
public string UserID { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
public string DateofBirth { get; set; }
public string ProfileImage { get; set; }
}
public async void makeRequest(String resourceUri)
{
HttpClient httpClient = new HttpClient();
try
{
HttpResponseMessage response = await httpClient.GetAsync(resourceUri);
}
catch (HttpRequestException hre)
{
Console.Write(hre.Message);
}
catch (TaskCanceledException)
{
}
}
remember to add Nuget packages: httpclient
Related
I have the following setup:
The document:
[BsonCollection("Users")] // I get the collection name with a custom extension
[BsonIgnoreExtraElements]
public class UserDocument
{
[BsonId]
public Guid Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public UserSettingsModel UserSettings { get; set; }
}
public class UserSettingsModel
{
// ...
}
The repository:
public class UserRepository
{
private readonly IMongoCollection<UserDocument> _collection;
private readonly ILogger<UserRepository> _logger;
public UserRepository(IMongoDatabase database, ILogger<UserRepository> logger)
{
// returns "Users"
var collectionName = typeof(UserDocument).GetCollectionName();
_collection = database.GetCollection<UserDocument>(collectionName);
}
// ...
public async Task<UserDocument> GetById(Guid id)
{
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, id);
var user = await _collection.FindAsync(filter);
// var user = await _collection.FindAsync(x => x.Id == id); - doesn't work either
var request = filter.Render(
_collection.DocumentSerializer,
_collection.Settings.SerializerRegistry).ToString();
_logger.LogDebug(request);
return user.FirstOrDefault();
}
}
And I initialize the client this way:
// ...
BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
var client = new MongoClient(connectionString);
var database = client.GetDatabase(dbName);
services.AddSingleton(c => database);
// convention pack and registries
// ...
// if moved here doesn't work either
// BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
The filter generated in GetById is still the following: { "_id" : CSUUID("459f165a-4a91-4f39-906c-dc7401ee2468") } when I expect it to be UUID instead of CSUUID.
So, the query doesn't find anything and returns null. In the database the document I'm searching for has _id: UUID('459f165a-4a91-4f39-906c-dc7401ee2468')
What am I doing wrong?
I was able to fixing by this trick:
var mongoConnectionUrl = new MongoUrl(connectionString);
var mongoClientSettings = MongoClientSettings.FromUrl(mongoConnectionUrl);
// before initializing client
mongoClientSettings.GuidRepresentation = GuidRepresentation.Standard;
However setting the GuidRepresentation in client settings is obsolete, which is quite confusing. Also, the query generated still has CSUUID instead of UUID. I was able to log the query the following way:
mongoClientSettings.ClusterConfigurator = cb =>
{
cb.Subscribe<CommandStartedEvent>(e => logger.LogDebug($"{e.CommandName} - {e.Command.ToJson()}"));
};
If anyone finds a better way and post it here it would be appreciated.
So far I have used this code to grab our azure devops project data. I have poked around the data and any urls returned looking for data related to pipelines and found nothing
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalAccessToken)));
ListofProjectsResponse.Projects viewModel = null;
//use the httpclient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://acme.visualstudio.com"); //url of our account
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
HttpResponseMessage response = client.GetAsync("/DefaultCollection/_apis/projects?stateFilter=All&api-version=1.0").Result;
//check to see if we have a succesfull respond
if (response.IsSuccessStatusCode)
{
//set the viewmodel from the content in the response
viewModel = response.Content.ReadAsAsync<ListofProjectsResponse.Projects>().Result;
}
}
public class ListofProjectsResponse
{
public class Projects
{
public int count { get; set; }
public Value[] value { get; set; }
}
public class Value
{
public string id { get; set; }
public string name { get; set; }
public string description { get; set; }
public string url { get; set; }
public string state { get; set; }
}
}
Did some changes on your main work code and share it below, just have a try:
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", "{PAT}")));
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://acme.visualstudio.com"); //url of our account
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
//HttpResponseMessage response = client.GetAsync("/_apis/projects?stateFilter=All&api-version=1.0").Result;
using (HttpResponseMessage response = await client.GetAsync("/ForMerlin/_apis/projects"))
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
// Console.WriteLine(response);
}
For BaseAddress, what you were using is an old URL format which like https://{org name}.visualstudio.com. This URL format has contain the organization name in it, so you can ignore the organization name when calling GetAsync. Just make it be /_apis/projects?stateFilter=All&api-version=1.0 is okay.
The way I found is to enumerate the builds for each project using the same code as above except
HttpResponseMessage response = client.GetAsync("/{org name}/{project
name}/_apis/build/builds?api-version=5.1").Result;
The url for each build will return a json collection with any azure build pipline data inside of "queue"
I have .NET Core Web App with the following controller:
[HttpPost]
public async Task<IActionResult> Update(StudentDetailsViewModel vm)
{
var tokenNo = HttpContext.Session.GetString("Token");
vm.ID = Convert.ToInt32(HttpContext.Session.GetString("StudentId"));
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenNo);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var putStudentUrl = _appSettings.Value.Apis.GSRTCApi.Url + _appSettings.Value.Apis.GSRTCApi.StudentsEndpoint + vm.ID;
var settings = new JsonSerializerSettings();
var stringData = JsonConvert.SerializeObject(vm);
var contentData = new StringContent(stringData, Encoding.UTF8, "application/json");
var response = await client.PutAsync(putStudentUrl, contentData); // contentData);
return RedirectToAction("Index", "Home");
}
The controller calls my Web API and everything works fine until I upload a file through my html form. When this happens the file is picked up in the IFormFile property of the StudentDetailsViewModel on the client side but when the API call is made the whole object is null. The API controller is:
[HttpPut("{id}")]
public async Task<IActionResult> Put(int? id, [FromBody]StudentViewModel student)
{
// API operations here
}
My suspicion is that I am not serializing the StudentDetailsViewModel object properly since I have a property IFormFile, which is an interface. However, I am not sure exactly how I need to customize the Json.Newsoft object.
For sending IFormFile, you need to use FromForm which is default when you remove FromBody and MultipartFormDataContent.
Here are complete steps:
Web App Model
public class StudentDetailsViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public IFormFile File { get; set; }
}
Web App Controller
public async Task<IActionResult> Update(StudentDetailsViewModel vm)
{
HttpClient client = new HttpClient();
var putStudentUrl = #"url";
byte[] data;
using (var br = new BinaryReader(vm.File.OpenReadStream()))
{
data = br.ReadBytes((int)vm.File.OpenReadStream().Length);
}
ByteArrayContent bytes = new ByteArrayContent(data);
MultipartFormDataContent multiContent = new MultipartFormDataContent();
multiContent.Add(bytes, "file", vm.File.FileName);
multiContent.Add(new StringContent(vm.Id.ToString()),"Id");
multiContent.Add(new StringContent(vm.Name), "Name");
var response = await client.PutAsync(putStudentUrl, multiContent);
return RedirectToAction("Index", "Home");
}
Web API Model
public class StudentViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public IFormFile File { get; set; }
}
Web API Controller
[HttpPut("{id}")]
public async Task<IActionResult> Put(int? id,StudentViewModel student)
{
using (var stream = new FileStream(#"file path", FileMode.Create))
{
await student.File.CopyToAsync(stream);
}
return Ok();
}
Pay attention to multiContent.Add(bytes, "file", vm.File.FileName);, the second parameter is the name for IFormFile field.
In our project, we are getting response from wcf service in xml format which we want to deserialize using datacontract serializer.
Below is the xml response.
<ArrayOfCustomerData xmlns="http://schemas.datacontract.org/2004/07/PACRM.QCT">
<CustomerData>
<AccountID>String content</AccountID>
<AccountName1>String content</AccountName1>
</CustomerData>
<CustomerData>
<AccountID>String content</AccountID>
<AccountName1>String content</AccountName1>
</CustomerData>
</ArrayOfCustomerData>
We have written the following DataContract class to deserialize the xml.
[DataContract]
public class ArrayOfCustomerData
{
[DataMember(Name="CustomerData")]
public CustomerData[] customerData { get; set; }
}
[DataContract]
public class CustomerData
{
[DataMember(IsRequired = true, Name = "AccountID")]
public string new_AccountID { get; set; }
[DataMember(IsRequired = true, Name = "AccountName1")]
public string new_accountname1 { get; set; }
}
C# code for deserialization is given below.
DataContractSerializer dcs = new DataContractSerializer(typeof(ArrayOfCustomerData));
ArrayOfCustomerData data=new ArrayOfCustomerData();
using (var stream = new StreamReader(response.GetResponseStream()))
{
var text=stream.ReadToEnd();
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(text));
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(ms, Encoding.UTF8);
dcs.WriteObject(xdw, data);
}
when i check the data.cusotmerData, it is returning null.
Can anyone please provide solution for this issue? Thanks!
You don't need the class ArrayOfCustomerData - that is just adding an unecessary extra element to the expected XML. You can use CustomerData[], as the type passed to the DataContractSerializer constructor, as shown below:
public class StackOverflow_24673714
{
const string XML = #"<ArrayOfCustomerData xmlns=""http://schemas.datacontract.org/2004/07/PACRM.QCT"">
<CustomerData>
<AccountID>String content ID 1</AccountID>
<AccountName1>String content name 1</AccountName1>
</CustomerData>
<CustomerData>
<AccountID>String content ID 2</AccountID>
<AccountName1>String content name 2</AccountName1>
</CustomerData>
</ArrayOfCustomerData>";
[DataContract(Name = "CustomerData", Namespace = "http://schemas.datacontract.org/2004/07/PACRM.QCT")]
public class CustomerData
{
[DataMember(IsRequired = true, Name = "AccountID")]
public string new_AccountID { get; set; }
[DataMember(IsRequired = true, Name = "AccountName1")]
public string new_accountname1 { get; set; }
}
public static void Test()
{
var ms = new MemoryStream();
var ws = new XmlWriterSettings { Indent = true, IndentChars = " ", OmitXmlDeclaration = true, Encoding = Encoding.UTF8 };
var w = XmlWriter.Create(ms, ws);
var dcs = new DataContractSerializer(typeof(CustomerData[]));
var obj = new CustomerData[] {
new CustomerData { new_AccountID = "String content 1", new_accountname1 = "String content 2" },
new CustomerData { new_AccountID = "String content 3", new_accountname1 = "String content 4" }
};
dcs.WriteObject(w, obj);
w.Flush();
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
var cds = (CustomerData[])dcs.ReadObject(ms);
Console.WriteLine(cds.Length);
foreach (var cd in cds)
{
Console.WriteLine(" {0} - {1}", cd.new_AccountID, cd.new_accountname1);
}
}
}
I have a class containing:
[Serializable]
public class ClsStatus
{
public byte[] Image { get; set; }
public string Status { get; set; }
public List<string> Servers { get; set; }
}
Now i am doing:
System.Drawing.Image image = null;
byte[] imageBytes = null;
// Create an image of the chart.
using (MemoryStream s = new MemoryStream())
{
chart.ExportToImage(s, System.Drawing.Imaging.ImageFormat.Jpeg);
image = System.Drawing.Image.FromStream(s);
imageBytes = s.ToArray();
}
ClsStatus status = new ClsStatus();
List<string> servers = new List<string>();
servers.Add("Server1");
servers.Add("Server2");
servers.Add("Server2");
status.Image = imageBytes;
status.Status = "Up & Running";
status.Servers = servers;
//XML Serialization
XmlDocument doc = new XmlDocument();
XmlSerializer serializer = new XmlSerializer(status.GetType());
MemoryStream stream = new MemoryStream();
try
{
serializer.Serialize(stream, status);
stream.Position = 0;
doc.Load(stream);
Response.ContentType = "text/xml";
Response.Clear();
Response.Write(doc.InnerXml);
}
catch
{
throw;
}
My Desired out put and what i am getting fro the above code is here:
http://i.stack.imgur.com/YgKgH.jpg
Is there any one who can help me in solving my issue?
Regards,
Mohin
XML is pretty much a text-based format, which means you're not going to be able to "see the image" in your XML document.
The closest you can get is to encode the binary image data into a "text" string (typically through Base64 encoding) and then embed the string into the XML document. That's exactly what you're getting now.