Updating record in winforms using Web API - c#

I'm pretty new to entity framework and Web services.
What I'm trying to do is updating records from winforms application by calling update method in Web API.
Httpresponse message returns bad request and doesn't update anything.
There is either a logical error with the code I wrote in api which updates records or the code I wrote in winform. I can't tell where the problem is.
Update method in API
[HttpPut]
public async Task <IActionResult> UpdateStatus ([FromBody]BookStatus entity)
{
var original = Tools.Context.BookStatus. Find(1);
Tools.Context.Entry (original).CurrentValues.SetValues (entity);
var result = await Tools.Context.SaveChangesAsync();
if (result > 0)
return Ok (result);
return Badrequest ();
}
Winform app where I call update method
private async void button3_click (object sender,EventArgs e)
{
BookStatus status = new BookStatus();
status.IsAvailable = true;
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback=(sender,cert,chain,sslPolicyError)=>{return true;};
HttpClient client = new HttpClient(clientHandler);
client.BaseAdress = new Uri ("Https://localhost:5001");
var serialize = JsonConvert.SerializeObject (status);
var content = new StringContent(serialize,Encoding.UTF8,"application/json");
var result = await client.PutAsJsonAsync ("api/BookStatus/UpdateStatus",content);
Message.Text = result.StatusCode.ToString ()";
}

I checked your codes and it seems that there was someting wrong with PutAsJsonAsync method ,and the webapi could not get the value of bookstatus.
I modified the codes in your winform client,and the webapi could get the value
private void button1_Click(object sender, EventArgs e)
{
BookStatus status = new BookStatus();
status.Id = 1;
status.IsAvailable = true;
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyError) => { return true; };
HttpClient client = new HttpClient(clientHandler);
var result1 = client.PutAsJsonAsync<BookStatus>("https://localhost:44318/WeatherForecast", status).Result;
}
Result:
And if you need help for your codes in your webapi project,you could tell me more details of your project such as your model class and Dbcontext

Related

How do I get the token to switch a camera's relay using ONVIF library?

I'm trying to set the camera's relay using the ONVIF library, but I can't get a token from the GetRelayOutputs() method.
I have seached several posts, but my problem must so simple that no one comments about it.
I have made a form with a single button for fast debbuging. Using the service reference https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl I already can get time, date, url etc...
public partial class Form1 : Form
{
DeviceClient deviceClient;
public Form1()
{
InitializeComponent();
ServicePointManager.Expect100Continue = false;
var endPointAddress = new EndpointAddress("http://172.16.2.119:8899/onvif/device_service");
var httpTransportBinding = new HttpTransportBindingElement { AuthenticationScheme = AuthenticationSchemes.Digest };
var textMessageEncodingBinding = new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None) };
var customBinding = new CustomBinding(textMessageEncodingBinding, httpTransportBinding);
var passwordDigestBehavior = new PasswordDigestBehavior("admin", "admin");
deviceClient = new DeviceClient(customBinding, endPointAddress);
deviceClient.Endpoint.Behaviors.Add(passwordDigestBehavior);
}
private void button1_Click(object sender, EventArgs e)
{
var relay = deviceClient.GetRelayOutputs();
deviceClient.SetRelayOutputState(relay.First().token, RelayLogicalState.active);
}
}
The DeviceClient object is being initialised as expected, but when I try to get the relay's outputs, it gives me a empty array.
Is there anything that I'm doing wrong?
Is it possible to a camera that has a relay not being able to use it with ONVIF?
Thank you.

How to avoid unreasonable long response time by using .net webclient with proxy?

I am trying to just request the webpage by using webclient DownloadString method with proxy.
The following is my code:
using (WebClient wc = new WebClient())
{
try
{
wc.Encoding = Encoding.UTF8;
wc.Proxy = new WebProxy(myProxy);
string result = wc.DownloadString(url);
}
catch (Exception ex)
{
//log exception
}
}
I have few proxies and almost all of them work well with above code.
However, sometimes the response return time is very very long (over an hour) and I believe it's due to my proxy slow issue.
But I don't understand that why it didn't throw exception since the webclient class should have an default timeout (I search default timeout that it should be 100 seconds).
Therefore I want to ask how to avoid this case?
Thanks everyone.
It will be complicated as you need two threads - one for download and one for cancellation on timeout.
wc.Encoding = Encoding.UTF8;
wc.Proxy = new WebProxy(myProxy);
string result = null;
var waitCancel = new CancellationTokenSource();
wc.DownloadStringCompleted += (sender, e) =>
{
if (e.Cancelled) return;
waitCancel.Cancel();
result = e.Result;
};
wc.DownloadStringAsync(url);
waitCancel.Token.WaitHandle.WaitOne(30 * 1000);
if (waitCancel.IsCancellationRequested == false)
{
wc.CancelAsync();
}
Console.WriteLine("Result: " + result);
First you need to make use of the "new" HttpClient for .Net, below I will illustrate in two steps
HttpClient has handlers you can place in a chain and then control how the whole client behaves, so in this case we will add a progress handler that will dictate behavior in regard to the speed of the transfer
if the transfer is too slow then cancel it and start a new one with different proxy in ur case ...
Create the progress handler (to tell us how the progress is going .. If too slow then throw an exception)
Type :
ProgressMessageHandler
"https://msdn.microsoft.com/en-us/library/system.net.http.handlers.progressmessagehandler(v=vs.118).aspx"
Note : Package (System.Net.Http.Formatting.Extension) required
We will wrap it with an own object to erase testing and configuring to certain expected transfer rate
Code :
public class MyOwnProgressHandlerContainer
{
private readonly long _expectedBytesTransferred;
private long _lastRecoredBytesTransferred = 0;
public MyOwnProgressHandlerContainer(long expectedBytesTransferred)
{
_expectedBytesTransferred = expectedBytesTransferred;
}
public void ReceivedProgressHandler(object sender, HttpProgressEventArgs e)
{
// you can uses e.ProgressPercentage but this is calculated based on content length
// http header which is very much ignored nowadays
if (_lastRecoredBytesTransferred != 0 && e.BytesTransferred < (_lastRecoredBytesTransferred + _expectedBytesTransferred))
throw new Exception("Too Slow, Abort !");
_lastRecoredBytesTransferred = e.BytesTransferred;
}
public void SendProgressHandler(object sender, HttpProgressEventArgs e)
{
// write stuff to handle here when sending data (mainly for post or uploads)
Console.WriteLine("Sent data ...");
}
}
Create the HttpClient and inject the handlers that we wrapped :)
Type :
HttpClient
https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx
Code :
// set expected rate
int expectedTransferRate = 25000; // AKA 2.5Mbps
// create own handler instance
MyOwnProgressHandlerContainer myHandler = new MyOwnProgressHandlerContainer(expectedTransferRate);
// create "ProgressMessageHandler"
ProgressMessageHandler progresshandler = new ProgressMessageHandler();
// Hookup event (send)
progresshandler.HttpSendProgress += myHandler.SendProgressHandler; // these are delegates so they can be a part of a stat-full class
// Hookup event (Receive)
progresshandler.HttpReceiveProgress += myHandler.ReceivedProgressHandler; // these are delegates so they can be a part of a stat-full class
// Create proxy handler
HttpClientHandler httpClientProxyHandler =
new HttpClientHandler
{
Proxy = new WebProxy("http://localhost:8888", false),
UseProxy = true
};
// Create client from factory with progress and "proxy" in your case
using (HttpClient httpClient = HttpClientFactory.Create(progresshandler, httpClientProxyHandler))
{
try
{
string downloadResult =
httpClient
// get result (progress handlers are notified based on sent / received data)
.GetAsync("https://httpbin.org/image/svg")
// could be a stream to read file content
.Result.Content.ReadAsStringAsync().Result;
Console.WriteLine(downloadResult);
}
catch (Exception)
{
// inspected if the exception is the same as the on u throw in MyOwnProgressHandlerContainer
throw;
}
}
WebClient doesnt have Timeout. You must extend it like this:
using System;
using System.Net;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
using (var webClient = new WebClientTimeOut())
{
webClient.Encoding = Encoding.UTF8;
webClient.Proxy = new WebProxy(myProxy);
try
{
var response = webClient.DownloadString("http://www.go1ogle.com");
Console.WriteLine(response);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
public class WebClientTimeOut : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
var w = base.GetWebRequest(uri);
w.Timeout = 1000; // Timeout 1 second
return w;
}
}
}

Wait until activity was closed

I use Xamarin Auth to authenticate with OneDrive in my android app. I assume this would work, but I have the issue that when the activity for the login prompt is opened the programm will just continue and not wait for the auth to finish.
How can I wait until it's closed or wrap this in a other way async?
Code:
private IDictionary<string, string> authenticationResponseValues;
protected override async Task<AccountSession> GetAuthenticationResultAsync()
{
await Task.Run(() => ShowWebView());
return new AccountSession(authenticationResponseValues, this.ServiceInfo.AppId, AccountType.MicrosoftAccount)
{
CanSignOut = true
};
}
private void ShowWebView()
{
var auth = new OAuth2Authenticator(
clientId: MSA_CLIENT_ID,
scope: string.Join(",", scopes),
authorizeUrl: new Uri(GetAuthorizeUrl()),
redirectUrl: new Uri(RETURN_URL));
auth.Completed += SetAccountInfos;
var intent = auth.GetUI(Application.Context);
intent.SetFlags(ActivityFlags.NewTask);
Application.Context.StartActivity(intent);
}
private void SetAccountInfos(object sender, AuthenticatorCompletedEventArgs eventArgs)
{
if (eventArgs.IsAuthenticated)
{
Debug.WriteLine(eventArgs);
Debug.WriteLine(eventArgs.Account == null ? "IS NULL" : "IS NOT NULL");
if (eventArgs.Account != null)
{
OAuthErrorHandler.ThrowIfError(eventArgs.Account.Properties);
authenticationResponseValues = eventArgs.Account.Properties;
}
}
}
I dont think using async tactic is reasonable, because app runs before login result returns.
Try to use sync way. Make a login page. If success, then switch to your real app.
I found a solution. Here my code:
await ShowWebView();
return new AccountSession(authenticationResponseValues, ServiceInfo.AppId,
AccountType.MicrosoftAccount)
{
CanSignOut = true
};
private Task<bool> ShowWebView()
{
var tcs = new TaskCompletionSource<bool>();
var auth = new OAuth2Authenticator(OneDriveAuthenticationConstants.MSA_CLIENT_ID, string.Join(",", OneDriveAuthenticationConstants.Scopes), new Uri(GetAuthorizeUrl()),
new Uri(OneDriveAuthenticationConstants.RETURN_URL));
auth.Completed += (sender, eventArgs) =>
{
if (eventArgs.IsAuthenticated)
{
OAuthErrorHandler.ThrowIfError(eventArgs.Account.Properties);
authenticationResponseValues = eventArgs.Account.Properties;
tcs.SetResult(true);
}
};
var intent = auth.GetUI(Application.Context);
intent.SetFlags(ActivityFlags.NewTask);
Application.Context.StartActivity(intent);
return tcs.Task;
}
And the link to the class in the repo: https://github.com/Apply-Solutions/MoneyManager/blob/master/Src/MoneyManager.Droid/Src/AndroidAuthenticationProvider.cs

Handle code after task are done

I'm trying to show a waiting symbol while while a ASYNC task are doing.
I'm really new to this, so if there are better ways to implement this code, please enlighten me :)
But, everything works except the hiding of the pictureBox1 after the code are done and there are now result found. In other words, when there are a result, the pictureBox1 are hidden
Here are the method that runs every time a outlook item are opened
private void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
if (this.OutlookItem is Microsoft.Office.Interop.Outlook.MailItem)
{
Microsoft.Office.Interop.Outlook.MailItem item = (Microsoft.Office.Interop.Outlook.MailItem)this.OutlookItem;
getContactByEmail(item);
}
}
This is the method that I implement the wait stuff
public async Task getContactByEmail(Microsoft.Office.Interop.Outlook.MailItem item)
{
pictureBox1.Visible = true;
using (var client = new System.Net.Http.HttpClient())
{
client.BaseAddress = new Uri("http://api.....");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = await client.GetAsync("tools/getContactByEmail?email=" + item.SenderEmailAddress + "&key=1232");
if (response.IsSuccessStatusCode)
{
SimpleContact contact = await response.Content.ReadAsAsync<SimpleContact>();
lblName.Text = contact.Name;
lblMobile.Text = contact.Phone;
}
pictureBox1.Visible = false;
}
}
Posting the code that fixes this so the exception are not raised
if (response.IsSuccessStatusCode)
{
SimpleContact contact = await response.Content.ReadAsAsync<SimpleContact>();
if (contact != null)
{
lblName.Text = contact.Name;
lblMobile.Text = contact.Phone;
}
pictureBox1.Visible = false;
}
In C# method names are always CamelCase and asynchronous methods are always suffixed Async. Just conventions.
You might want to extract the non UI code to another asynchronous method to avoid going back and forth to the UI thread:
private async void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
if (this.OutlookItem is Microsoft.Office.Interop.Outlook.MailItem)
{
Microsoft.Office.Interop.Outlook.MailItem item = (Microsoft.Office.Interop.Outlook.MailItem)this.OutlookItem;
pictureBox1.Visible = true;
var contact = GetContactByEmailAsync(item);
if (contact != null)
{
lblName.Text = contact.Name;
lblMobile.Text = contact.Phone;
}
pictureBox1.Visible = false;
}
}
public async Task<SimpleContact> GetContactByEmailAsync(Microsoft.Office.Interop.Outlook.MailItem item)
{
using (var client = new System.Net.Http.HttpClient())
{
client.BaseAddress = new Uri("http://api.....");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = await client.GetAsync(
"tools/getContactByEmail?email=" + item.SenderEmailAddress + "&key=1232")
.ConfigureAwait(false);
return (response.IsSuccessStatusCode)
? await response.Content.ReadAsAsync<SimpleContact>();
: null;
}
}
Note: Don't forget proper exception handling!!!

Windows Store app webservice consume

I have a windows phone 7 app with following code
ServiceReference1.SMSWarriorServiceSoapClient ws = new ServiceReference1.SMSWarriorServiceSoapClient();
ws.BalanceCompleted += new EventHandler<ServiceReference1.BalanceCompletedEventArgs>(ws_BalanceCompleted);
ws.BalanceAsync(textBox1.Text, textBox2.Password);
Now i want to make it also for Windows 8 store app. I try this
var client = new ServiceReference1.SMSWarriorServiceSoapClient() ;
var result = client.BalanceAsync("user", "pass");
resultDetails.Text = result.ToString ;
but with no luck
I also try the Await but I don't know how to use it
If you are calling the web service method from an event handle then use this.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
var client = new ServiceReference1.SMSWarriorServiceSoapClient();
var result = await client.BalanceAsync("user", "pass");
resultDetails.Text = result.ToString();
}
If you are calling the web service method from a method then use this.
private async Task ServiceCall()
{
var client = new ServiceReference1.SMSWarriorServiceSoapClient();
var result = await client.BalanceAsync("user", "pass");
resultDetails.Text = result.ToString();
}
Ensure you call method ServiceCall() with await keyword.
if u use await then u must use async keyword or use Task
var client = new ServiceReference1.SMSWarriorServiceSoapClient() ;
var result = await client.BalanceAsync("user", "pass");
resultDetails.Text = result.ToString ;
for example:
// Put the keyword, async on the declaration of the event handler.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
var respose=await <some async operation >
}

Categories

Resources