I'm a student trying to set up a WCF service. I got the host and client running with a servicelibrary, and it works fine until my client tries to call upon a service that accesses a library (Gamez) I've made. The method it calls upon works fine normally, it's just through the WCF that it suddenly crashes it.
So say it calls upon this:
public int AddValues(int a, int b)
{
int c = a + b;
return c;
}
It'll work fine, but this:
public Guid GetUserId(String userName)
{
Guid user = Gamez.Sql.GetIdFromUserName(userName);
return user;
}
=boom. Keep in mind that the GetIdFromUserName method works fine when called on from non-WCF-related code.
This is the client-side code:
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
Service1Client client = new Service1Client();
client.Open();
String gameName = "Liksomspill";
String userName = "Grouse";
//int result = client.GetHighScore(userName, gameName);
//Console.WriteLine("highscoren er: {0}", result);
//Guid result = client.GetUserId(userName);
//Console.WriteLine("blablabla: {0}", result);
int a = 5;
int b = 2;
int result2 = client.AddValues(a, b);
Console.WriteLine("highscoren er {0}", result2);
Console.WriteLine();
Console.ReadLine();
client.Close();
}
}
}
This will work fine as long as it stays like this (so it'll return 7), but if I remove commenting from these lines:
Guid result = client.GetUserId(userName);
Console.WriteLine("blablabla: {0}", result);
the top line will throw an exception, but I have no idea what it is as it only says "FaultException`1 was unhandled" with subtext "The type initializer for 'Gamez.Sql' threw an exception.". I've tried looking this up, but I don't really understand how to fix this (I'm coding in Visual Studio 2012). Here are some of the links I found on the subject, but it's just massively confusing me:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/1829b844-1237-4390-8d36-76a7e42a64d3/
http://sergecalderara.wordpress.com/2008/11/25/systemservicemodelfaultexception1-was-unhandled-by-user-code/
I'm sure there is just something basic which I am completely overseeing (...you are supposed to be able to call libraries with the wcf service, right? Or do I have to incorporate the parts of my library I want to use into the service library?). I've added references to the library so that shouldn't be a problem. I'm sorry if this question is kinda stupid, but I'm tearing myself apart in frustration after banging my head against the issue for six hours.
If you need some background information, I'm basically trying to set up an API for games uploaded to a website I'm making (so the games can extract/insert highscores, etc. from the database).
Thank you so much for your time.
If needed, here is the host code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using WcfServiceLibrary;
using System.ServiceModel.Description;
namespace WCFHost
{
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8000/WCF");
ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);
ServiceDebugBehavior debug = selfHost.Description.Behaviors.Find<ServiceDebugBehavior>();
if (debug == null)
{
selfHost.Description.Behaviors.Add(
new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
}
else
{
if (!debug.IncludeExceptionDetailInFaults)
{
debug.IncludeExceptionDetailInFaults = true;
}
}
try
{
//selfHost.Open();
selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "Service1Service");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("The service is ready");
Console.WriteLine("Press enter to terminate service");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occured: {0}", ce.Message);
selfHost.Abort();
}
}
}
}
And here is the ServiceLibrary code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Gamez;
namespace WcfServiceLibrary
{
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public void SetHighScore(int score, String userName)
{
}
public int GetHighScore(String userName, String gameName)
{
int score = Gamez.Sql.getHighScore(userName, gameName);
return score;
}
public Guid GetUserId(String userName)
{
Guid user = Gamez.Sql.GetIdFromUserName(userName);
return user;
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
public int AddValues(int a, int b)
{
int c = a + b;
return c;
}
}
}
Related
I am trying to check if the program svchost is running which is actually Windows service.
If that service is not running, start it again. I mean if the user try to end the task from task manager start it again.
You can do like this.
ServiceController sc = new ServiceController(ServiceName);
if (sc.Status == ServiceControllerStatus.Running)
{
//do something
}
else
{
sc.Start();
}
I would say check for ServiceControllerStatus.Stopped status and then start the service.
and to answer your other question how to get PID.
int pid= Process.GetProcessesByName(ServiceName)[0].Id;
Update from previous answer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Management;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
var data = IsServiceActive("unstoppable");
Console.WriteLine("PID: {0}, Status: {1}", data.Id, data.Status);
Console.ReadLine();
}
private static SrvData IsServiceActive(string srvname)
{
string status = "NA";
int id = -1;
ServiceController[] srvc = ServiceController.GetServices();
foreach (var sr in srvc)
{
if (sr.ServiceName == srvname)
{
// get status
status = sr.Status.ToString();
// get id
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" + srvname + "'");
wmiService.Get();
id = Convert.ToInt32(wmiService["ProcessId"]);
break;
}
}
SrvData result = new SrvData() { Id = id, Status = status };
return result;
}
}
public class SrvData
{
public string Status { get; set; }
public int Id { get; set; }
}
}
I am attempting to use a managed code action in an InstallShield suite project.
I followed their example in hopes it wouldn't be a big deal.
http://helpnet.flexerasoftware.com/installshield21helplib/helplibrary/SteActionManagedCd.htm
Ideally, I want to have my .dll method to change an install shield property when the action is executed. When I test out the installer to see if the property changed, I get the default value I set.
Maybe I am doing it wrong, any suggestions would be greatly appreciated.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Web.Administration;
namespace IISHelp
{
[Guid("BAFAEAED-08C6-4679-B94E-487A4D89DE63")]
[TypeLibType(4288)]
public interface ISuiteExtension
{
[DispId(1)]
string get_Attribute(string bstrName);
[DispId(2)]
void LogInfo(string bstr);
[DispId(3)]
string get_Property(string bstrName);
[DispId(3)]
void set_Property(string bstrName, string bstrValue);
[DispId(4)]
string FormatProperty(string bstrValue);
[DispId(5)]
string ResolveString(string bstrStringId);
}
public class Help
{
const UInt32 ERROR_INSTALL_FAILURE = 1603;
const UInt32 ERROR_SUCCESS = 0;
ISuiteExtension GetExtensionFromDispatch(object pDispatch)
{
if (Marshal.IsComObject(pDispatch) == false)
throw new ContextMarshalException("Invalid dispatch object passed to CLR method");
return (ISuiteExtension)pDispatch;
}
public UInt32 IsUniqueName(object pDispatch)
{
try
{
List<string> currentVirtualDirectories = GetApplicationNames();
ISuiteExtension suiteExtension = GetExtensionFromDispatch(pDispatch);
var name = suiteExtension.get_Property("APPLICATION_NAME");
suiteExtension.set_Property("IS_UNIQUE_APPLICATION_NAME", (!currentVirtualDirectories.Contains(name)).ToString());
}
catch (System.ContextMarshalException)
{
return ERROR_INSTALL_FAILURE;
}
return ERROR_SUCCESS;
}
public List<string> GetApplicationNames()
{
List<string> currentVirtualDirectories = new List<string>();
ServerManager mgr = new ServerManager();
foreach (Site s in mgr.Sites)
{
foreach (Application app in s.Applications)
{
currentVirtualDirectories.Add(app.Path.Replace('/', ' ').Trim());
}
}
return currentVirtualDirectories.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
}
}
}
when i run a method within my WCF service i get "An unhandled exception of type 'System.StackOverflowException' occurred in developer1SVC.dll".
No infinite loops exist and no infinite recursion is occurring. Any ideas to why this may be happening? when i run the method through wcf test client. I get the results back correctly however, hooking it up to my console app and running it breaks the application. The other methods run fine. It is this one method. Just trying to get the feel for WCF services. The service breaks right after i return accounts from the "generateMultiplAccounts" method.
Much help appreciated.
Service
using developer1.Core.ServiceContracts;
using developer1.Core.Data;
using developer1.Core.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using developer1.Core.Dto.Account;
namespace developer1.Core.Service
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
Console.WriteLine(composite.StringValue + composite.BoolValue);
return composite;
}
public List<AccountDto> GenerateMultipleAccounts(int count)
{
List<AccountDto> accounts = new List<AccountDto>();
for (int i = 0; i < count; i++)
{
AccountDto newAccount = new AccountDto() { AccountId = Guid.NewGuid()};
accounts.Add(newAccount);
}
return accounts;
}
}
}
Console Application
using developer1.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using developer1.Core.Service;
using developer1.Core.Dto.Account;
using developer1.Core.ServiceContracts;
using AccountServiceClient = developer1.TestConsole.ServiceReference1.Service1Client;
namespace developer1.TestConsole
{
class Program
{
static void Main(string[] args)
{
try
{
AccountServiceClient AccountServiceClient = new AccountServiceClient();
Guid testGuid = Guid.NewGuid();
List<AccountDto> newAccounts = new List<AccountDto>(AccountServiceClient.GenerateMultipleAccounts(2));
Console.WriteLine(testGuid);
CompositeType testDataContract = new CompositeType() { StringValue = "test", BoolValue = true };
testDataContract = AccountServiceClient.GetDataUsingDataContract(testDataContract);
Console.WriteLine(AccountServiceClient.GetData(6));
Console.WriteLine(testDataContract.StringValue);
//foreach (var item in newAccounts)
//{
// Console.WriteLine(item.AccountId);
//}
}
catch(Exception e) {
Console.WriteLine(e);
}
Console.Read();
}
}
}
Data Contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
namespace developer1.Core.Dto.Account
{
[DataContract]
public class AccountDto
{
[DataMember]
public Guid AccountId { get; set; }
//get { return this.AccountId; }
//set { this.AccountId = this.AccountId == Guid.Empty ? Guid.NewGuid() : value; }
[DataMember]
public Guid UserId { get; set; }
[DataMember]
public string AccountName { get; set; }
[DataMember]
public string BankName { get; set; }
//get { return this.BankName; }
//set { this.BankName = this.BankName == null ? "Unspecified" : value; }
}
}
ANSWER!!!!!!!
So I have solved this dreaded issue. You must create a WCF Service Library instead of a WCF Service Application. My god that is stupid that the application wont let you split your components outside of the interface.
Im trying to communicate with two pc's via an ethernet cable. I've gone into the settings and told it to use two specific ip addresses. Ive turned the firewalls off on both pc's and managed to ping from one pc to the other. When i try and use the following code, its not working though. Something about nothing listening at the specified address. Any ideas?
//SERVER
using System;
using System.ServiceModel;
namespace WCFServer
{
[ServiceContract]
public interface IStringReverser
{
[OperationContract]
string ReverseString(string value);
}
public class StringReverser : IStringReverser
{
public string ReverseString(string value)
{
char[] retVal = value.ToCharArray();
int idx = 0;
for (int i = value.Length - 1; i >= 0; i--)
retVal[idx++] = value[i];
return new string(retVal);
}
}
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(
typeof(StringReverser),
new Uri[]{
new Uri("http://192.168.10.10")
}))
{
host.AddServiceEndpoint(typeof(IStringReverser),
new BasicHttpBinding(),
"Reverse");
host.Open();
Console.WriteLine("Service is available. " +
"Press <ENTER> to exit.");
Console.ReadLine();
host.Close();
}
}
}
}
//CLIENT
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace WCFClient
{
[ServiceContract]
public interface IStringReverser
{
[OperationContract]
string ReverseString(string value);
}
class Program
{
static void Main(string[] args)
{
ChannelFactory<IStringReverser> httpFactory =
new ChannelFactory<IStringReverser>(
new BasicHttpBinding(),
new EndpointAddress(
"http://192.168.10.9"));
IStringReverser httpProxy =
httpFactory.CreateChannel();
while (true)
{
string str = Console.ReadLine();
Console.WriteLine("http: " +
httpProxy.ReverseString(str));
}
}
}
}
The Address your service is listening to is http://192.168.10.10/Reverse (Uri you gave plus endpoint name you gave), you should connect your client to this endpoint instead of http://192.168.10.9.
I am working on an assignment and I am getting this error which I don't understand. I am writing a WCF client for a working service. Can anyone help me out here?
This line is throwing the error:
MyComplex sumcplx = proxy.complex_sum(one,two);
Error I get
Error: The best overloaded method match for 'NETProxyWCFClient.ProxyTypes.CalculatorClient.complex_sum(NETProxyWCFClient.ProxyTpes.MyComplex,NETProxyWCFClient.ProxyTpes.MyComplex)' has some invalid arguments
Code to my program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.ServiceModel.Description;
namespace NETProxyWCFClient
{
[DataContract]
public class MyComplex
{
int real;
[DataMember]
public int Real
{
get { return real; }
set { real = value; }
}
[DataMember]
int im;
public int Im
{
get { return im; }
set { im = value; }
}
}
[ServiceContract]
interface ICalculator
{
[OperationContract]
int mult(int a, int b);
[OperationContract]
List<int> fib(int n);
[OperationContract]
MyComplex complex_sum(MyComplex a, MyComplex b);
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter in 2 numbers");
string read = Console.ReadLine();
string[] numbers = read.Split(' ');
int m = int.Parse(numbers[0]);
int n = int.Parse(numbers[1]);
ProxyTypes.CalculatorClient proxy = new ProxyTypes.CalculatorClient();
//Multiplcation
int sum = proxy.mult(m, n);
Console.WriteLine(sum.ToString());
//Mycomplex
MyComplex one = new MyComplex();
one.Im = m;
one.Real = n;
MyComplex two = new MyComplex();
two.Im = n;
two.Real = m;
MyComplex sumcplx = proxy.complex_sum(one,two);
Console.WriteLine(sumcplx.Im + " , " + sumcplx.Real);
//fib one
int[] listM = proxy.fib(m);
foreach (int listItem in listM)
{
Console.Write(listItem.ToString() + " ");
}
Console.WriteLine("");
//fib 2
int[] listN = proxy.fib(n);
foreach (int listItem in listN)
{
Console.Write(listItem.ToString() + " ");
}
Console.ReadLine();
}
}
}
If you have Added a service reference to your test program, there is a proxt class that is generated for you, so if you have ICalculator defined explicity (code you wrote) remove it. it is already in your project, under the NETProxyWCFClient.ProxyTpes.MyComplex,NETProxyWCFClient.ProxyTpes namespace.