How to choose a WCF service to connect to? - c#

I have two separate servers with identical WCF services (let's say, WS1 and WS2) and a C# Mobile CF 2.0 project that need to access both of the services.
Can I do something like this on the C# CF2.0 project?
(...)
if (someCondition == true)
{
WS1 aux = new WS1();
}
else
{
WS2 aux = new WS2();
}
aux.service(parameter1);
(...)
note that I want to have the same variable name, independent of which server I'll access. The problem is: I don't know how to declare it outside the conditional statements and when I just declare it inside the conditional statements they're declared as local variables and I don't know how to make the variable public or global.
Any thoughts or help, please?

Since the WCF Service is exactly the same, just running on different servers, then from your client project simply add a service reference to one of them (WS1 for example). This will generate the client proxy for you. Perhaps give it a generic name too, like "serviceX" (replacing X with something appropriate for your application).
Then, in your client config file, copy the client endpoint it created and add another endpoint with the only difference being the address and the endpoint name. Maybe you want to set the endpoint name property on each endpoint to be "WS1" and "WS2" respectively.
Then, in your code, you should be able to do something like this:
(...)
serviceXClient aux = null;
if (someCondition == true)
{
aux = new serviceXClient("WS1");
}
else
{
aux = new serviceXClient("WS2");
}
aux.service(parameter1);
(...)

If you're using .Net 4.0 or higher you could use dynamic typing.
http://msdn.microsoft.com/en-us/library/dd264736.aspx

Related

Using global C# variables in Typescript

When writing Javascript code within a Razor/cshtml file, one may write code as follows:
if (lSelectedID == "#(Globals.MyGlobalVariable)") {
...
}
where Globals.MyGlobalVariable is a C# variable.
If Globals.MyGlobalVariable==123, then the resulting Javascript on the client will be
if (lSelectedID == "123") {
...
}
The above is very handy. But how to do the same in Typescript? I.e. how to insert a C# global variable (or result of C# function call or whatever) into typescript before the typescript file is transformed to Javascript?
It's not best practice to include JavaScript and CSS directly into your CSTHML. Rather you should have them in their own file and reference them in your view.
If your JavaScript is going to need some value from C# then you should store it by using data attribute in your HTML elements.
Example:
<span id="myGlobalVariable" data-value="123456">MyGlobalVariable</span>
Then in your TypeScript get data you have set in your View
let myGlobalVariable = document.getElementById("myGlobalVariable").dataset.value;
if (lSelectedID == myGlobalVariable) {
}
I think the easiest thing to do here would be to replicate your global variables in Typescript on the client side. This is how I've done it for my last two projects.
So on the server side you would have:
// C#
public class Globals()
{
public int GlobalNum {get;} = 0;
public string GlobalString {get;} = "123";
}
And on the client side, in Typescript it would be:
// Typescript
export enum Globals{
GlobalNum = 0;
GlobalString = "123";
}
Now you can forget about the difficulty of trying to connect Razor (which renders server-side) to your Typescript (which executes on the client side), while still having a clear and obvious set of globals to refer to.
You code can then become:
// Typescript
if (lSelectedID == Globals.GlobalString) {
//...
}
The only thing you need to keep in mind is that your global variables exist in two places - once on the server side and once on the client side.
Typescript demands that you replicate a lot of your server-side classes on the client side anyway, for receiving fetch response data properly, for example, so the addition of a Globals class/enum should not be too much of a break from the norm.

Using a "shared" type on a WCF/MVC project with two services ("cannot convert from...")

I've two WCF services connected to my client. I want to use a User-object, retrieved from service #1, and use this as paramter for service #2. Here is my MVC-Controller TournamentController.cs code:
private readonly GCTournamentServiceClient _tournamentClient = new GCTournamentServiceClient();
public ActionResult Join(int id)
{
GCUserServiceClient userClient = new GCUserServiceClient();
// Get current user
var currentUser = userClient.GetUser(0);
if (currentUser != null)
{
// Get selected tournament
var selectedTournament = _tournamentClient.GetTournament(id);
// Check if there are available seats in the tournament
if (selectedTournament.Seats > selectedTournament.RegistredUsers.Count)
{
// Check if user exist amoung registred users
if (!selectedTournament.RegistredUsers.Contains(currentUser))
{
selectedTournament?.RegistredUsers.Add(currentUser);
}
}
}
}
The error Visual Studio prompt me with:
Argument 1: cannot convert from 'GConnect.Clients.WebClient.GCUserService.User' to 'GConnect.Clients.WebClient.GCTournamentService.User'
So the problem is currentUser, which has the type GCUserService.User. I'm unable to use this as parameter for RegistredUsers
The error itself makes perfect sense, however, I'm not quite sure how I'm suppose to convert this type (properly). Some articles states, that a "shared"-service has to be created, which holds the User-type. I just can't believe, that a solution like that, should be necessary.
I might have misunderstood some basic stuff here (working with WCF and MVC), but please enlighten me, if that's the case.
So the problem is currentUser, which has the type GCUserService.User.
I'm unable to use this as parameter for RegistredUsers
There are 2 approaches to solve this problem:
1)
Create a class library project (Visual Studio) and add the User class in that project, compile it and add its assembly's (.dll) reference to both services and the client (your MVC application). Next retrieve that user object as you are already doing it
var currentUser = userClient.GetUser(0);
GetUser will return the type of User that is defined in a separate assembly which is added as reference as suggested above. The TournamentService will also reference the same assembly and the RegistredUsers.Add(User userToadd) method will take the same User object and WCF runtime should be able to serialise/desterilise it.
2)
In your MVC client application, new up the User object that is acceptable by the TournamentService.RegistredUsers.Add method. Populate its properties from the currentUser and pass in that object as parameter to RegistredUsers.Add method.
Best Practice
Ideally, I would recommend the first approach which is more work but a better practice and that your User class is maintained centrally and code is reused.
Hope this helps!

Declare generic Service Reference client object for scoping issue

I have this in my web.config
If this value is live, then I want to call the live web service, and if it's not, then I want to call the test web service.
In my code I want to do something like this:
if (System.Configuration.ConfigurationManager.AppSettings["runMode"] == "live")
{
var client = new CallStatusAvailability.ServiceReference1
.StatusAvailabilityRoomsClient();
}
else
{
var client = new CallStatusAvailability.StatusAvailabilityRooms
.StatusAvailabilityRoomsClient();
}
using (client)
{
...... lots of logic
}
The problem is that client is out of scope. I would like to be able to declare client before the if statement, but not sure what I can define it as?
I could put the using statement within the if or the else statement, but I would then have to duplicate all the logic in both.
At first I tried to create a function that could be called from the if and the else, and pass in client, but then I face the same issue of what type to declare the input client variable as, as an input to the function.
I would suggest that you not add both service references to your project, but a single service reference (probably to the test service) and vary the connection parameters using configuration transforms. You would do this by setting your base web.config up to connect to the test service, then add a transform in web.Release.config to change the binding when deployed using the Release target. This will simplify your logic to the point where you won't need the if-else construct and allow you to create the client within a using statement.
Your issue is that var is declaring a variable. If you need to use a variable in this way you can't use var as it need to be declared at a higher level of scope. Just move your declaration to the containing block. This assumes the service references are using the same type; if not, you need to fix that first or use dynamic if they are semantically identical. You also can't use a using in this context and must use try catch finally.
To use the same types I would suggest generating the proxy using the channel factory or using svcutil so that your types are the same for the different service references.
CallStatusAvailability.ServiceReference1.StatusAvailabilityRoomsClient client = null;
try
{
if (System.Configuration.ConfigurationManager.AppSettings["runMode"] == "live")
{
client = new CallStatusAvailability.ServiceReference1.StatusAvailabilityRoomsClient();
}
else
{
client = new CallStatusAvailability.StatusAvailabilityRooms.StatusAvailabilityRoomsClient();
}
}
catch(..){}
finally
{
client.Dispose();
}

Reporting Services Web Service, C# .NET code reuse

I'm building a custom front-end for a collection of reporting services servers. I'm adding the ReportingServices2005 web reference to my project using;
http://server/ReportServer_InstanceName/ReportService2005.asmx?wsdl
At the moment my approach is to add this reference for each server, however I'm then struggling with the code reuse aspect. The reporting services classes are then different namespaces.
I'd like to have a method as below;
public string ListReports(Server1WebService.ReportingService2005 service) {
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
service.Server1WebService.CatalogItem[] children = service.ListChildren("/", true);
string list = String.Empty;
foreach (Server1WebService.CatalogItem i in children) {
if (!i.Hidden)
list += i.Name + "</br>";
}
return list;
}
To make this method reusable I need to know how to refactor this so that any instance of the ReportingService2005 class can be passed regardless of the namespace. At the moment I have to specify Server1WebService for all references to ReportingService2005 and CatalogItem.
Provided that all of the SSRS instances are the same version, You should be able to set the URL property on the proxy object:
Server1WebService server.url = new uri ("http://server/ReportServer_InstanceName/ReportService2005.asmx?wsdl"));
If you have multiple versions to deal with, you may need to provide some type of factory object that can correctly instantiate the correct version.
Hope this helps

dynamic binding of web service URI

I have a list of servers, all exposing the same web service interface, that I need to call from my code.
i.e.
https://server1/service.asmx
https://server2/service.asmx
https://server3/service.asmx
My code needs to get this list of servers and invoke the same function on all of them.
I added a web references to this service, and I use "Dynamic" URL behavior. This is supposed to let me create an instance of the server proxy object, set the URI property at runtime, and then invoke the web methods, right?
But it seems the code generated by VS assumes the URI will come from the application's config file, which isn't the case for this app.
public SharpEyeWebService() {
this.Url = global::Company.DotNet.MyProject.Properties.Settings.Default.MyWebService;
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
}
else {
this.useDefaultCredentialsSetExplicitly = true;
}
}
Is it safe to ignore the default URL the constructor uses and employ the approach I described above?
You can always set the Url, so yes this is safe. The "dynamic" you describe only influences the default Url: whether it hard-coded or comes from config.
So indeed, this is moot if you are supplying this yourself.
The awkward bit here is that it also sets UseDefaultCredentials based on what it finds - so it would be worth setting this manually so you know the value.

Categories

Resources