开发者

Changing method of connecting to server C#

I need to change how my C# application connects to a server to send a request and get a response. I'm not great with C# so I apologize if this explanation is confusing. Currently the program appears to use some magic that uses static information from the app.config file:

<configuration>
  <system.serviceModel>
    <client>
      <!-- important information here -->
    </client>
  </system.serviceModel>
</configuration>

I tried changing the values inside of the <client> element, but this only reads changes on program restart.

I would like to connect in a different way. Here is what I envision: I can access the data in the app.config file, store that in a few variables, and allow the user to change the values as necessary. They hit the "connect" button when they've tweaked the values to work for them, and THEN I make the connection with this code. I tried to find an answer to this but I couldn't find any tutorials on how to do this, so any links are appreciated too.

(this question is spawned from the answers to this question)

All help is appreciated and thanks in advance!

EDIT:

I have Hoerster's solution mostly working, but I got a few errors with his, so I changed the following lines:

Uri calcService = new Uri("http://localhost:8000/ServiceModelSamples/Service/CalculatorService");

(using direct URI because I didn't want to mess with app.config)

CalculatorClient.CalculatorClient calcClient = new CalculatorClient.CalculatorClient(calcBinding, calcEndpoint);

I had my service reference named CalculatorClient, so I had to instantiate a CalculatorClient from that reference, thus the double "CalculatorClient".

When I run my client (with the service running) I get the following exception in my client:

An unhandled exception of type 'System.ServiceModel.ProtocolException' occurred in mscorlib.dll

Additional information: Content Type text/xml; charset=utf-8 was not supported by service http://localhost:8000/ServiceModelSamples/Service/CalculatorService.  The client and service bindings may be mismatched.

I'm a bit confused by this because I d开发者_开发百科idn't touch any of the Reference.cs code. It hovers over the following line in my Reference.cs:

return base.Channel.Add(n1, n2);

I feel like I'm really close to getting this figured out, but that I'm just missing one thing...


Well, sounds like there's two questions here:

  1. How to get app.config to update during runtime (which is possible, but isn't automatic); and,
  2. How to dynamically set bindings and endpoints at runtime based upon app.config settings.

For updating your app.config at runtime, call RefreshSection. So you would probably want to hook up that call to the client button click event.

ConfigurationManager.RefreshSection("appSettings");
Console.WriteLine(ConfigurationManager.AppSettings["foo"]);

For dynamically setting your binding and endpoint information at runtime, that's definitely possible. I put a quick example together based on the MSDN Calculator Service examples. (I used BasicHttpBinding instead of WSHttpBinding just to keep it simple.) UPDATE Here's the only change I made to the example service:

// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(
    typeof(ICalculator),
    new BasicHttpBinding(),
    "CalculatorService");

The steps I took were:

  1. Create the service from the MSDN code sample and run it (so that the service endpoint was listening);
  2. Created a basic C# console application and added a service reference to my service so that it would create the client reference classes in my client console app. (It also created an app.config, but I'm not using any of those app.config settings it created.);
  3. Wrote the following code which sets up the Binding and EndpointAddress that my auto-generated client code will use to connect to the service:

*

static void Main(string[] args) {
    //refresh the appSettings section
    ConfigurationManager.RefreshSection("appSettings");

    //this could come from app.configs appSettings (value = "http://localhost:8000/ServiceModelSamples/Service/CalculatorService")
    Uri calcService = new Uri(ConfigurationManager.AppSettings["uri"]);
    Binding calcBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
    EndpointAddress calcEndpoint = new EndpointAddress(calcService.AbsoluteUri);


    CalculatorClient calcClient = new CalculatorClient(calcBinding, calcEndpoint);
    double sum = calcClient.Add(10, 20);
    double difference = calcClient.Subtract(sum, 10);

    Console.WriteLine("10 + 20 = {0}", sum.ToString());
    Console.WriteLine("{0} - 10 = {1}", sum.ToString(), difference.ToString());

    Console.ReadLine();
}

That should do it. So you can make the parameters to the Binding and EndpointAddress constructors read in from your configuration file (or user entry), and you can set additional Binding and EndpointAddress properties as you see fit.

Hopefully this helps. Let me know if there are additional questions and I'll update my answer accordingly.

UPDATE 2 (now with WSHttpBinding!!) I updated this to include using WSHttpBinding (with message level security) as a second example. There's a lot of different ways to handle security with WCF, and MSDN has a nice guide on configuring your security accordingly based upon your scenario. Here's the link to that page.

So my updated example is basically the same as above, except the client creates a WSHttpBinding instead of BasicHttpBinding, and specifies Message level security as the SecurityMode.

static void Main(string[] args)
{
    //refresh the appSettings section
    ConfigurationManager.RefreshSection("appSettings");

    //this could come from app.configs appSettings (value = "http://localhost:8000/ServiceModelSamples/Service/CalculatorService")
    Uri calcService = new Uri(ConfigurationManager.AppSettings["uri"]);

    //create the WsHttpBinding and set some security settings for the transport...
    WSHttpBinding calcBinding = new WSHttpBinding(SecurityMode.Message);
    EndpointAddress calcEndpoint = new EndpointAddress(calcService.AbsoluteUri);


    CalculatorClient calcClient = new CalculatorClient(calcBinding, calcEndpoint);
    double sum = calcClient.Add(10, 20);
    double difference = calcClient.Subtract(sum, 10);

    Console.WriteLine("10 + 20 = {0}", sum.ToString());
    Console.WriteLine("{0} - 10 = {1}", sum.ToString(), difference.ToString());

    Console.ReadLine();
}

The only difference I made on the server was that I specified WSHttpBinding when adding my service endpoint. Again, I chose the binding defaults, but that MSDN link above will describe how to configure the server based on your security needs.

// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(
    typeof(ICalculator),
    new WSHttpBinding(),
    "CalculatorService");

I hope this helps! Just remember that anything you can do in WCF configuration you can do in code. There's a 1:1 relationship between configuration settings and code (basically, everything in configuration translates to some WCF class that you can use).

Good luck! Let me know if there are other questions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜