Self Hosting WebApi C# with WindowsForms error - c#

I took a sample project webapi Self Hosting, the Microsoft page. The webapi starts correctly, but when accessing the address, it gives the error below. I'm using VS2010 and Windows Forms. With Console Applicattion its working, and Windows Forms not working.
Program code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web.Http.SelfHost;
using System.Web.Http;
using System.Net.Http;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
HttpSelfHostServer server;
HttpSelfHostConfiguration config;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var config = new HttpSelfHostConfiguration("http://localhost:9090");
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
}
}
private void button2_Click(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:9090");
//Console.WriteLine("Products in '{0}':", category);
string query = string.Format("api/products?category={0}", "testes");
var resp = client.GetAsync(query).Result;
//resp.EnsureSuccessStatusCode();
var products = resp.Content.ReadAsAsync<string>().Result;
MessageBox.Show(products);
}
}
}
Controller:
namespace SelfHost
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http;
public class ProductsController : ApiController
{
public string GetProductsByCategory(string category)
{
return (category ?? "Vazio");
}
}
}
Error:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Object reference not set to an instance of an object.
</ExceptionMessage>
<ExceptionType>System.NullReferenceException</ExceptionType>
<StackTrace>
at System.Web.Http.SelfHost.HttpSelfHostServer.ProcessRequestContext(ChannelContext channelContext, RequestContext requestContext)
</StackTrace>
</Error>

Your code has a bunch of mistakes which I see, and I don't think that I can include them all in commentary. Maybe if you will fix them - this exception will gone.
Issues:
Right after this code server.OpenAsync().Wait(); you call Dispose method on server (because you wrapped everything in using statement). This means that when OpenAsync will be finished (and this task will be finished when server is running) - right after this you will close the server.
You have a bunch of deadlocks on main thread when you call Wait on the task. Check this article http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx on this.
This is my try to rewrite your example to fix these two issues:
public partial class Form1 : Form
{
HttpSelfHostServer server;
HttpSelfHostConfiguration config;
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
config = new HttpSelfHostConfiguration("http://localhost:9090");
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
HttpSelfHostServer server = new HttpSelfHostServer(config);
await server.OpenAsync();
// Server is running: you can show something to user like - it is running
MessageBox.Show("Server is ready!");
}
private async void button2_Click(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:9090");
string query = string.Format("api/products?category={0}", "testes");
var resp = await client.GetAsync(query);
var products = await resp.Content.ReadAsAsync<string>();
MessageBox.Show(products);
}
}

Related

WP8.1 HttpClient doesn't download string after first request

I'm wondering for a few days what's going on. I'm writing an app for Windows Phone 8.1 that uses HttpClient to download json string from Internet. It works fine BUT only once after running the app (in OnNavigatedTo event). Later, smashing 'Refresh' button that is supposed to download string again doesn't work. It's still the same string value that has been download as first. On server, this string changes and I can confirm that by looking at it in browser on PC.
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace WP8App
{
public sealed partial class MainPage : Page
{
private readonly Uri Website = new Uri("https://some-website.com/files/status.json");
private HttpClient http = new HttpClient();
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Refresh();
}
private async void Button_Refresh_Click(object sender, RoutedEventArgs e)
{
Refresh();
}
private async void Refresh()
{
var response = await http.GetStringAsync(Website);
JsonObject api = JsonConvert.DeserializeObject<JsonObject>(response);
TextBox_A.Text = api.value;
TextBox_B.Text = api.length;
TextBox_C.Text = api.size;
TextBox_F.Text = api.volume;
}
private async void ShowDialog(string value)
{
MessageDialog box = new MessageDialog(value);
await box.ShowAsync();
}
}
}
I'm not a master at async, so I count on your eagle eyes xD Thanks
Requests caching is very aggressive on Windows Phone. The easiest way to bypass it is adding a random parameter at the end of the URL. Something like:
private readonly string Website = "https://some-website.com/files/status.json?nocache={0}";
Then change the value every time you use it. Using the current timestamp is a good and cheap way to ensure that the URL will always be different:
var response = await http.GetStringAsync(new Uri(string.Format(Website, DateTime.UtcNow.Ticks));

Bluetooth listener - how to listen messages from Bluetooth devices

I'm trying to create a server (a computer with Bluetooth) that listen to Bluetooth messages. I'm using 32 feet library. But I'm getting a exception, and I cannot find what it is.
The exception is:
No supported Bluetooth protocol stack found.
here is the code:
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using InTheHand;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Ports;
using InTheHand.Net.Sockets;
using System.IO;
namespace Bluetoot_Tutorial
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void bGo_Click(object sender, EventArgs e)
{
connectAsServer();
}
private void connectAsServer()
{
Thread bluetoothServerThread = new Thread(new ThreadStart(ServerConnectThread));
bluetoothServerThread.Start();
}
private void connectAsClient()
{
throw new NotImplementedException();
}
Guid uUUID = new Guid("00001101-0000-1000-8000-00805F9B34FB");
public void ServerConnectThread()
{
BluetoothListener blueListener = new BluetoothListener(uUUID);
blueListener.Start();
BluetoothClient conn = blueListener.AcceptBluetoothClient();
}
The message means what it says... What Bluetooth software do you have on your PC?
Add Local address in BluetoothListener like below.
BluetoothRadio myRadio = BluetoothRadio.PrimaryRadio;
if (myRadio == null)
{
Console.WriteLine("No radio hardware or unsupported software stack");
return;
}
RadioMode mode = myRadio.Mode;
var lsnr = new BluetoothListener(myRadio.LocalAddress, serviceClass);
lsnr.Start();

Windows form loads then quits

I'm creating a checkout system for a supermarket. It consists of a checkout, server and MIS program an operates WCF services between them. The problem I have is that the checkout program, which is a windows form, does a few neccessaries in it's application_load method and then just quits.
Here's the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CheckoutLibrary;
using Checkout.ServerLibraryService;
using Checkout.MarketService;
namespace Checkout
{
public partial class theForm : Form
{
private static int checkoutID = 3;
private Product[] allProducts;
public theForm()
{
InitializeComponent();
}
private void theForm_Load(object sender, EventArgs e)
{
// First cache all products
SupermarketServiceSoapClient marketService = new SupermarketServiceSoapClient();
allProducts = marketService.GetAllProducts();
// Load the service provided by the server
ServiceClient serverService = new ServiceClient();
// Load the event handlers for the bar code scanner
BarcodeScanner scanner = new BarcodeScanner();
scanner.ItemScanned += new BarcodeScanner.ItemScannedHandler(scanner_ItemScanned);
scanner.AllItemsScanned += new BarcodeScanner.AllItemsScannedHandler(scanner_AllItemsScanned);
scanner.Start(checkoutID);
}
void scanner_AllItemsScanned(EventArgs args)
{
throw new NotImplementedException();
}
void scanner_ItemScanned(ScanEventArgs args)
{
itemTextBox.Text = "Scanned " + GetItemName(args.Barcode);
}
private void scanItemButton_Click(object sender, EventArgs e)
{
scanner_ItemScanned(new ScanEventArgs(GetRandBarcode()));
}
// A barcode -> product name look up method
public string GetItemName(int barcode)
{
return allProducts[barcode].Description + " # " + allProducts[barcode].Price;
}
// Method to grab a random barcode for simulation
private int GetRandBarcode()
{
Random rand = new Random();
return rand.Next(0,500);
}
}
}
And program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Checkout
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new theForm());
}
}
}
Thanks for any insight.
In WinForms, if your form_load throws an exception, it quits without displaying anything. Annoying, but I'm guessing that's the problem.
You can try a try/catch, or you can hit CTRL+ALT+E and check the Thrown Column for Common Language Runtime Exceptions to see the error.
UPDATE:
Based on comments, here's a sample way to execute something on another thread.
ThreadStart ts = new ThreadStart(() => {
try {
scanner.Start(checkoutID);
} catch {
// Log error
}
});
Thread t = new Thread(ts);
t.Start();

Does WqlEventQuery contain a constructor with 1 argument?

I am trying to create a simple service in C# using VS2008 that creates a text file when the computer goes into sleep mode. My current code throws out the following error:
'SleepNotifierService.WqlEventQuery' does not contain a constructor that takes '1' arguments
Now I looked in the Object browser, and it looks like it does take in one argument. This is what the browser had to say:
public WqlEventQuery(string queryOrEventClassName)
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Management;
using System.IO;
namespace SleepNotifierService
{
public class WqlEventQuery : EventQuery { }
public partial class Service1 : ServiceBase
{
ManagementEventWatcher _watcher;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WqlEventQuery query = new WqlEventQuery("Win32_PowerManagementEvent");
_watcher = new ManagementEventWatcher(query);
_watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
_watcher.Start();
}
protected override void OnStop()
{
_watcher.Stop();
}
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
try
{
int eventType = Convert.ToInt32(e.NewEvent.Properties["EventType"].Value);
switch (eventType)
{
case 4:
Sleep();
break;
case 7:
Resume();
break;
}
}
catch (Exception ex)
{
//Log(ex.Message);
}
}
public void Sleep()
{
StreamWriter SW;
SW = File.CreateText("c:\\MyTextFile.txt");
SW.WriteLine("Sleep mode initiated");
SW.Close();
}
public void Resume()
{
}
}
}
Am I interpreting that object browser wrong? I'm new to creating services and C#/.NET in general so it might be something trivial.
Appreciate any help,
Tomek
You're using wrong WqlEventQuery. There's one defined in System.Management and it indeed has a one-argument constructor, but there's also your custom WqlEventQuery class.
If you want to use .NET BCL's class, you'll have to fully qualify it:
var query = new System.Management.WqlEventQuery("Win32_PowerManagementEvent");
or even prefix it with global keyword:
var query = new global::System.Management.WqlEventQuery("Win32_PowerManagementEvent");

How can I call this webservice asynchronously?

In Visual Studio I created a web service (and checked "generate asynchronous operations") on this URL:
http://www.webservicex.com/globalweather.asmx
and can get the data out synchronously but what is the syntax for getting the data out asychronously?
using System.Windows;
using TestConsume2343.ServiceReference1;
using System;
using System.Net;
namespace TestConsume2343
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
GlobalWeatherSoapClient client = new GlobalWeatherSoapClient();
//synchronous
string getWeatherResult = client.GetWeather("Berlin", "Germany");
Console.WriteLine("Get Weather Result: " + getWeatherResult); //works
//asynchronous
client.BeginGetWeather("Berlin", "Germany", new AsyncCallback(GotWeather), null);
}
void GotWeather(IAsyncResult result)
{
//Console.WriteLine("Get Weather Result: " + result.???);
}
}
}
Answer:
Thanks TLiebe, with your EndGetWeather suggestion I was able to get it to work like this:
using System.Windows;
using TestConsume2343.ServiceReference1;
using System;
namespace TestConsume2343
{
public partial class Window1 : Window
{
GlobalWeatherSoapClient client = new GlobalWeatherSoapClient();
public Window1()
{
InitializeComponent();
client.BeginGetWeather("Berlin", "Germany", new AsyncCallback(GotWeather), null);
}
void GotWeather(IAsyncResult result)
{
Console.WriteLine("Get Weather Result: " + client.EndGetWeather(result).ToString());
}
}
}
I suggest using the event provided by the auto-generated proxy instead of messing with the AsyncCallback
public void DoWork()
{
GlobalWeatherSoapClient client = new GlobalWeatherSoapClient();
client.GetWeatherCompleted += new EventHandler<WeatherCompletedEventArgs>(client_GetWeatherCompleted);
client.GetWeatherAsync("Berlin", "Germany");
}
void client_GetWeatherCompleted(object sender, WeatherCompletedEventArgs e)
{
Console.WriteLine("Get Weather Result: " + e.Result);
}
In your GotWeather() method you need to call the EndGetWeather() method. Have a look at some of the sample code at MSDN. You need to use the IAsyncResult object to get your delegate method so that you can call the EndGetWeather() method.

Categories

Resources