I am learning WCF and as part of the learning, i found out that the namespace for the contracts should match. I wrote a contract class (both client and host have their own copy) and made their namespace to not match but my code still works. I have provided code for my contract and host class and how client is calling the contract. could someone please advise where i am wrong?
Client Contract Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace GeoLib.Client.Contracts
{
[ServiceContract]
public interface IMessageContract
{
[OperationContract (Name = "ShowMessage")]
void ShowMsg(string message);
}
}
Host Contract Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace GeoLib.WindowsHost.Contracts
{
[ServiceContract]
public interface IMessageContract
{
[OperationContract]
void ShowMessage(string message);
}
}
Calling Code in Client:
private void btnMakeCall_Click(object sender, RoutedEventArgs e)
{
ChannelFactory<IMessageContract> factory = new ChannelFactory<IMessageContract>("");
IMessageContract proxy = factory.CreateChannel();
proxy.ShowMsg(txtMessage.Text);
factory.Close();
}
Namespace in ServiceContracts or DataContracts are usually used for versioning as they allow for two objects with the same name to exist in different namespaces.
It seems, however, that you haven't defined a Namespace for your Service.
Defining a namespace would be like:
[ServiceContract (Namespace="http://yourcompany.com/MyService/V1")]
public interface IMessageContract
{
...
}
If you later introduce a new version of your Service with new implementation and put it in a separate namespace such as:
[ServiceContract (Namespace="http://yourcompany.com/MyService/V2")]
public interface IMessageContract
{
...
}
then you can keep the two services separated and have old clients calling version1 and new clients calling version2
Related
I'm trying to make an interface like this
using System;
using System.IO;
using System.Text;
using System.Threading;
using Xamarin.Forms;
namespace Foo
{
public interface IStreamProvider
{
Stream OutputStream { get; set; }
}
}
and implement it in the iOS project like this:
using System;
using System.IO;
using Foundation;
using Foo;
[assembly: Xamarin.Forms.Dependency(typeof(StreamProvider_iOS))]
namespace Foo.iOS
{
public class StreamProvider_iOS : IStreamProvider
{
public Stream OutputStream { get; set; }
}
}
but I end up getting this error:
'StreamProvider_iOS ' does not implement interface member
'IStreamProvider.OutputStream'. 'StreamProvider_iOS.OutputStream'
cannot implement 'IStreamProvider.OutputStream' because it does not
have the matching return type of 'Stream'.
I'm thinking it's because System.IO in the base xamarin project isn't the same as System.IO in the Xamarin.iOS project, but I'm not really sure and don't know how to work around that if it's the case.
I am new to WCF and I am using "Learning WCF: A Hands-on Guide" book for now. The book has used VS2008 for the examples, and I am not sure what Visual Studio IDE to use for the examples. I tried using VS Express for Web and it gives the following error:
"HelloIndigo.exe does not contain static Main method suitable at entry point'.
I can understand the cause of the issue, but I am not sure where to add the main method. So I used VS Express for Desktop and it worked fine, but as I kept going in the first chapter I could not proceed as there are no WCF service templates in the VS Express for Desktop version. VS2012 is available only in trial version for free, and it expires in 90 days. So what IDE should I should be using? If the answer is VS Express for Web, then how to fix the error for the example in first chapter?
The example provided in the book is
Host:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
namespace Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(HelloIndigo.HelloIndigoService),new Uri("http://localhost:8000/HelloIndigo")))
{
host.AddServiceEndpoint(typeof(HelloIndigo.IHelloIndigoService), new BasicHttpBinding(), "HelloIndigoService");
host.Open();
Console.WriteLine("Please <ENTER> to terminate the service host");
Console.ReadLine();
}
}
}
}
HelloIndigo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
namespace HelloIndigo
{
public class HelloIndigoService : IHelloIndigoService
{
public string HelloIndigo()
{
return "Hello Indigo";
}
}
[ServiceContract(Namespace="http://www.thatindigogirl.com/samples/2006/06")]
public interface IHelloIndigoService
{
[OperationContract]
string HelloIndigo();
}
}
Client:
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
namespace Client
{
class Program
{
static void Main(string[] args)
{
EndpointAddress ep = new EndpointAddress("http://localhost:8000/HelloIndigo/HelloIndigoService");
IHelloIndigoService proxy = ChannelFactory<IHelloIndigoService>.CreateChannel(new BasicHttpBinding(), ep);
string s = proxy.HelloIndigo();
Console.WriteLine(s);
Console.WriteLine("Please <ENTER> to terminate client");
Console.ReadLine();
}
}
}
ServiceProxy.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
namespace Client
{
class ServiceProxy
{
}
[ServiceContract(Namespace = "http://www.thatindigogirl.com/samples/2006/06")]
public interface IHelloIndigoService
{
[OperationContract]
string HelloIndigo();
}
}
HelloIndigo should be compiled as a library (DLL) and not an executable. So there should be no Main method - it doesn't have one as a class library.
The point of the Host is that it will host the service library HelloIndigo and start listening for calls on an endpoint for that particular service.
Change HelloIndigo to compile as a class library and add a reference to HelloIndigo in Host. Then start up the Host process.
I'm trying to implement authorization into an existing WCF-service.
To do that I following a Microsoft Pattern & practices tutorial.
At Step 5, the service class should derive from IService, however my existing service class does not and when I add : IService to my class Visual Studio doesn't recognize it.
How can I derive from the interface as described in the article?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;
namespace MyCompanyNamespace.API.IISServiceHost
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class CompanyNameAPIService : IService //not recognized!
{
public ApproveitAPIService()
{
}
}
}
From my point of view you have to Implement IService by yourself like in this Microsoft-Example.
I’m pretty new to programming, so bear with me if my question isn’t specific enough. Right now I’m trying to make a simple Client Logon to my server. So the server App knows which users are connected. When a client connects I want an event to fire on the server that update the userlist. But it doesn’t and I can’t figure out why. Hope you can help.
In the codes I have removed how the users should be displayed in the serverApp. Right now I just need the event to work.
In my Service Library:
INetworkService contract:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace NetworkLib
{
[ServiceContract]
public interface INetworkService
{
[OperationContract]
void Logon(UserInfo userInfo);
[OperationContract]
void Logout();
}
}
NetworkService Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace NetworkLib
{
public class NetworkService : INetworkService
{
public event EventHandler UserListChanged;
public void Logon(UserInfo userInfo)
{
OnUserListChanged();
}
public void Logout()
{
OnUserListChanged();
}
private void OnUserListChanged()
{
var handler = UserListChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
}
UserInfo Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace NetworkLib
{
[DataContract]
public class UserInfo
{
[DataMember]
public string Name;
}
}
In my ServerApp (WPF):
using System.ServiceModel;
using NetworkLib;
namespace ServerApp
{
public partial class MainWindow : Window
{
NetworkService networkService;
public MainWindow()
{
InitializeComponent();
ServiceHost host = new ServiceHost(typeof(NetworkService));
host.Open();
networkService = new NetworkService();
networkService.UserListChanged += networkService_UserListChanged;
}
private void networkService_UserListChanged(object sender, EventArgs e)
{
MessageBox.Show("It Works!");
}
}
}
In my ClientApp (WPF): (Have made a Service Reference to the Server)
namespace ClientApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
ServiceReference.NetworkServiceClient proxy = new ServiceReference.NetworkServiceClient();
ServiceReference.UserInfo userInfo = new ServiceReference.UserInfo();
userInfo.Name = "Test";
proxy.Logon(userInfo);
}
}
}
You subscribe to event of other NetworkService instance than ServiceHost instantiates. In your case every time you make request to server, new NetworkService instance is created. Place the following attribute above NetworkService class:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
Then subscribe to event:
var serviceInstance = (NetworkService)host.SingletonInstance;
serviceInstance.UserListChanged += networkService_UserListChanged;
When creating your ServiceHost, you should provide NetworkService instance instead of typeof(NetworkService)
ServiceHost host = new ServiceHost(networkService);
You need to initialize it first, of course.
I didnt look in great detail but overall your code looks ok. It is sometimes useful in this situation to run 2 instances of VisualStudio - one for server in debug and one for client in debug. If you put a break point in client button1_Click code in VS thats debugging client, and a break point in NetworkServices.Logout in VS thats debugging server you will be able to step from client to server code and see easily whats going wrong where.
Why do you need an event model here? Why not just handle your "event" directly in NetworkService.Logout(). Does pushing this off to an event and then having to wire that event (which as ilya.dofofeev correctly points out is not on the same object) provide any real benefit?
I am reading Designing Evolvable Web APIs with ASP.NET. In one of the exercises, the book has me edit a Controller using Visual Studio. This is being done in ASP.NET using C#. The template I used was the standard ASP.NET web application API.
I have edited the controller to the way the book shows (although it does not seem to give very specific directions). Here is what my controller looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using WebApplication4.Models;
using WebApplication4.Providers;
using WebApplication4.Results;
namespace WebApplication4.Controllers
{
public class GreetingController : ApiController
{
public string GetGreeting() {
return "Hello World!";
}
}
public static List<Greeting> _greetings = new List<Greeting>();
public HttpResponseMessage PostGreeting(Greeting greeting)
{
_greetings.Add(greeting);
var greetingLocation = new Uri(this.Request.RequestUri, "greeting/" + greeting.Name);
var response = this.Request.CreateResponse(HttpStatusCodeResult.Created);
response.Headers.Location = greetingLocation;
return response;
}
}
I get errors on:
_greetings: A namespace cannot directly contain members such as fields or methods
PostGreeting: A namespace cannot directly contain members such as fields or methods,
_greetings : does not exist in the current context
Request : <invalid-global-code> does not contain a definition for 'request',
Created: HttpStatusCodeREsult does not contain a definition for 'Created'
As the error is trying to tell you, your fields and methods must be inside the class.
Check your braces.
Your _greetings field needs to be part of the class, as well as the PostGreeting method, it seems you just closed "}" of the class a bit early.
MOve the "}" before the _greetings field to the end of the file, like:
namespace WebApplication4.Controllers
{
public class GreetingController : ApiController
{
public string GetGreeting() {
return "Hello World!";
}
public static List<Greeting> _greetings = new List<Greeting>();
public HttpResponseMessage PostGreeting(Greeting greeting)
{
_greetings.Add(greeting);
var greetingLocation = new Uri(this.Request.RequestUri, "greeting/" + greeting.Name);
var response = this.Request.CreateResponse(HttpStatusCodeResult.Created);
response.Headers.Location = greetingLocation;
return response;
}
}
}