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.
Related
I'm learning about WCF, and made a C# fiddle of custom class in the interface that has its own GetEnumerator() method to customize the class' foreach behaviour. The class is as shown:
ProductClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ProductInterfaces
{
public class ProductData : IEnumerable
{
public string Name { get; set; }
public string ProductNumber { get; set; }
public string Color { get; set; }
public double ListPrice { get; set; }
List<string> myData = new List<string>(new string[] { "test1", "test2", "test3", "test4" });
public IEnumerator<string> GetEnumerator()
{
foreach(string val in myData)
{
yield return val;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
And the contract is as shown (IWCFProductService.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace ProductInterfaces
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IWCFProductService" in both code and config file together.
[ServiceContract]
public interface IWCFProductService
{
[OperationContract]
ProductData GetProduct(string productNumber);
}
}
The implementation of the GetProduct() method is as shown:
using ProductInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace ProductService
{
public class WCFProductService : IWCFProductService
{
public ProductData GetProduct(string productNumber)
{
using (adventureworksEntities database = new adventureworksEntities())
{
var table_of_products = database.products;
ProductData desired_product = new ProductData();
foreach (var p in table_of_products)
{
if (p.ProductNumber == productNumber)
{
Console.WriteLine("Test using a custom foreach of ProductData class");
foreach (string i in desired_product)
{
Console.WriteLine(i);
}
desired_product.Name = p.Name;
desired_product.ProductNumber = p.ProductNumber;
desired_product.Color = p.Color;
desired_product.ListPrice = p.ListPrice;
return desired_product;
}
}
throw new Exception();
}
}
}
}
When called by the client:
using ProductInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace ProductClient
{
class Program
{
static void Main(string[] args)
{
// Client creates channel factory by passing in the name of the endpoint (i.e. ProductServiceEndpoint)
ChannelFactory<IWCFProductService> channelFactory = new ChannelFactory<IWCFProductService>("ProductServiceEndpoint");
// Create a proxy i.e. create a channel
IWCFProductService proxy = channelFactory.CreateChannel();
Console.WriteLine("Input product name to be searched:");
string input = Console.ReadLine();
var searchResult = proxy.GetProduct(input);
Console.WriteLine(searchResult.Name);
Console.ReadLine();
}
}
}
It fails at var searchResult = proxy.GetProduct(input);, with exception saying
System.ServiceModel.CommunicationException: 'An error occurred while receiving the HTTP response to http://localhost:9999/ProductService. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.'
I did some trial and error, and if I remove IEnumerable and the foreach loop, there is no issue and searchResult is a valid object. Why is this happening? Am I understanding something wrong?
I think it should be a serialization issue, WCF needs to have concrete classes to pass data.
It cannot return IEnumerable - try using List (or T[] array) or concrete types.
You can also use the Service Trace Viewer to find specific issues.
Posts with similar questions
WCF Web Service error: "Service endpoint binding not using HTTP protocol"?
This could be due to the service endpoint binding not using the HTTP protocol
i am trying to make an angular application that takes an api made from asp.net core but while making the api , it didn't work and appear as planned and didn't know where was the problem...
I made an asp.net core web app.
This is the student.cs file made in the model folder
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI101.Model
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public bool Pass { get; set; }
}
}
This is the studentmanager also in model folder
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI101.Model
{
public class StudentManager
{
public List<Student> GetResults()
{
List<Student> oList = new List<Student>();
var r = new Random();
for(int i = 0; i < 10; i++)
{
var x = new Student();
x.ID = i;
x.Name = String.Format("Name{0}", i, ToString());
x.Pass = (r.Next() % 2 == 0);
oList.Add(x);
}
return oList;
}
}
}
This is the code that should return aaaaa
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI101.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StudentController : ControllerBase
{
[Route("mariam")]
public string test()
{
return "aaaaa";
}
}
}
I tried to launch the code and it didn't work as planned o the link:https://localhost:5001/api/Student/mariam
The problem is you are using [Route("mariam")] which overrides the controller route.
You need to use [HttpGet("mariam")] instead.
[HttpGet("mariam")]
public string test()
{
return "aaaaa";
}
Using HttpGet will add to the controller route.
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 have the following code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using OpenFridge.Portable.Data.Interfaces.Entities;
using OpenFridge.Portable.Data.Parse.Entities;
using Parse;
using AutoMapper;
namespace OpenFridge.Portable.Data.Parse.Entities
{
[ParseClassName("_User")]
public class ParseUserEntity : ParseUserEntityBase, IUserEntity
{
private string _password;
[ParseFieldName("password")]
public new string Password
{
get { return _password; }
set
{
_password = value;
base.Password = value;
}
}
Lazy<IEnumerable<IBankAccountEntity>> _bankAccounts;
[ParseFieldName("bankAccounts")]
public Lazy<IEnumerable<IBankAccountEntity>> BankAccounts
{
get
{
var relation = GetRelation<ParseBankAccountEntity>("BankAccount");
if (relation == null) return null;
var result = relation.Query.FindAsync().Result;
var _bankAccounts = new Lazy<IEnumerable<IBankAccountEntity>>(() => relation.Query.FindAsync().Result);
return _bankAccounts;
}
set
{
_bankAccounts = value;
}
}
}
}
And it all seems to work quite fine, however.. once I use the .BankAccounts property I get the following exception:
Must specify a ParseObject class name when creating a ParseQuery.\r\nParameter name: className
Which I find strange since there is no way for me to define a classname with in that line of code:
(That line of code beeing:)
relation.Query.FindAsync().Result
So.. is this a bug?.. Am I doing something wrong or using it wrong?
Any ideas?
Br,
Inx
I'm trying to create a simple service using the code provided but i don't understand why have an exception when binding.
10-19 11:42:09.148 I/mono-stdout( 1622): MvxBind:Error: 10.40 Exception thrown during the view binding
MvxBindingLayoutInflatorFactory Line 133!
I need some help please :)
My Source:
DataStore Interface:
using Core.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace Core.Interfaces
{
public interface IDataStore
{
void UpdateFeed(FeedModel feedModel);
void DeleteFeed(FeedModel feedModel);
void CreateFeed(FeedModel feedModel);
FeedModel GetFeed(Uri uri);
ObservableCollection<FeedModel> Feeds { get; }
}
}
DataStore Class:
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Interfaces;
using System.Collections.ObjectModel;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Interfaces.Platform;
using Cirrious.MvvmCross.Interfaces.Localization;
using Cirrious.MvvmCross.ExtensionMethods;
using Core.Helpers;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.IO;
namespace Core.Models
{
public class DataStore
: IDataStore
, IMvxServiceConsumer<IMvxSimpleFileStoreService>
, IMvxServiceConsumer<IMvxResourceLoader>
{
public DataStore()
{
Load();
}
public void UpdateFeed(FeedModel feedModel)
{
var toUpdate = this.m_feeds.First(feed => feed.Url == feedModel.Url);
toUpdate.CloneFrom(feedModel);
Save();
}
public void DeleteFeed(FeedModel feedModel)
{
this.m_feeds.Remove(this.m_feeds.First(feed => feed.Url == feedModel.Url));
Save();
}
public void CreateFeed(FeedModel feedModel)
{
this.m_feeds.Add(feedModel);
Save();
}
public FeedModel GetFeed(Uri uri)
{
return this.m_feeds.First(feed => feed.Url == uri);
}
private void Load()
{
var fileService = this.GetService<IMvxSimpleFileStoreService>();
if (!fileService.TryReadBinaryFile(LocationDataService.StoreFileName, LoadFrom))
{
var resourceLoader = this.GetService<IMvxResourceLoader>();
resourceLoader.GetResourceStream(LocationDataService.ResourceFileName, (inputStream) => LoadFrom(inputStream));
}
}
private bool LoadFrom(Stream inputStream)
{
try
{
var loadedData = XDocument.Load(inputStream);
if (loadedData.Root == null)
return false;
using (var reader = loadedData.Root.CreateReader())
{
var list = (List<FeedModel>)new XmlSerializer(typeof(List<FeedModel>)).Deserialize(reader);
this.m_feeds = new ObservableCollection<FeedModel>(list);
return true;
}
}
catch
{
return false;
}
}
private void Save()
{
var fileService = this.GetService<IMvxSimpleFileStoreService>();
fileService.WriteFile(LocationDataService.StoreFileName, (stream) =>
{
var serializer = new XmlSerializer(typeof(List<FeedModel>));
serializer.Serialize(stream, m_feeds.ToList());
});
}
private ObservableCollection<FeedModel> m_feeds;
public ObservableCollection<FeedModel> Feeds
{
get { return this.m_feeds; }
}
}
}
BaseViewModel:
using Cirrious.MvvmCross.Commands;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.Commands;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.ViewModels;
using Core.Interfaces;
namespace Core.ViewModels
{
public class BaseViewModel
: MvxViewModel
, IMvxServiceConsumer<IDataStore>
{
protected IDataStore DataStore
{
get { return this.GetService<IDataStore>(); }
}
}
}
FeedManagerViewModel:
using Cirrious.MvvmCross.Commands;
using Cirrious.MvvmCross.Interfaces.Commands;
using Core.Controls;
using Core.Models;
using System;
using System.Collections.ObjectModel;
namespace Core.ViewModels
{
public class FeedsManagerViewModel
: BaseViewModel
{
public ObservableCollection<FeedModel> Feeds { get { return this.DataStore.Feeds; } }
...
}
}
View xml:
<Mvx.MvxBindableListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="{'ItemsSource':{'Path':'Feeds'}, 'ItemClick':{'Path':'DisplayItemCommand'}}"
local:MvxItemTemplate="#layout/feedlist_viewmodel" />
This is most likely an error in your XML... but it's hard to tell from just that one line of trace.
What version of MvvmCross are you running?
The tip version of both Master and vNext show line 133 as
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Exception during creation of {0} from type {1} - exception {2}", name, viewType.FullName, exception.ToLongString());
So hopefully if you use the tip, then that should give you a lot more information about what is going wrong.
Beyond that, you can always try setting a breakpoint on the offending line to extract more information.
If the exception is on line 99 then change the error logging there from:
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Exception thrown during the view binding ", exception.ToLongString());
to:
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Exception thrown during the view binding {0}", exception.ToLongString());
The error will be in there somewhere :)
Another good debugging technique is to comment out lines one-by-one until the problem goes away - this helps identify where the problem is.
You've got a working development environment and a really powerful debugger - using it is a good skill to learn. 'Code Complete' is one of my favourite books ever :)