Error in Retrieving Objects from WCF Service - c#

New to WCF Services and needs some help.
So I have a client (basic console app) to test the WS (which is hosted on a test server not localhost)
With it I can pass and retrieve standard objects like string and int to and fro.
I can also pass custom classes to the WS but not retrieve them. I get either timeout or
An error occurred while receiving the http response to... 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 the
the service shutting down)
The underlying connection was closed. An unexpected error occurred on receive.
Unable to read data from the transport connection, an existing connection
was forcibly closed by the remote host.
I searched about endpoints and every single one seemed different and not obviously adaptable I am currently using the stock web.config when the project was created below which I think is where my issue is but finding difficult to know what to put.
WS Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings />
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
<connectionStrings>
<add name="CNS" connectionString="xyz" providerName="System.Data.EntityClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
Service Method in Question
public Request GetOrderByRef(string Ref)
{
AssetStockEntity db = new AssetStockEntity();
try
{
RequestEntity _requestef = new RequestEntity();
_requestef = db.RequestEntities.FirstOrDefault(x => x.Incident == Ref);
if (_requestef == null)
return null;
else
return TranslateRequestEntityToRequest(_requestef);
}
catch (Exception ex)
{
string debug = ex.ToString();
}
}
EDIT
Database Connection Test (Works as expected)
public string GetOrderByRefTest(string Ref)
{
AssetStockEntity db = new AssetStockEntity();
try
{
RequestEntity _requestef = new RequestEntity();
_requestef = db.RequestEntities.FirstOrDefault(x => x.Incident == Ref);
if (_requestef == null)
return null;
else
return _requestef.Requested_By;
}
catch (Exception ex)
{
string debug = ex.ToString();
return debug;
}
}
I'm using the translate call to convert EF objects to prevent exposure as from what I can understand is bad.
Class
[DataContract]
public class Request
{
[DataMember]
public int RId { get; set; }
[DataMember]
public string Incident { get; set; }
[DataMember]
public string Requested_By { get; set; }
[DataMember]
public string Authorised_By { get; set; }
[DataMember]
public virtual ICollection<Request_Items> Request_Items { get; set; }
}
Interface
[ServiceContract]
public interface Iws
{
[OperationContract]
Request GetOrderByRef(string Ref);
}
Test Console
static void Main(string[] args)
{
ASM.IwsClient ws = new ASM.IwsClient();
try
{
Console.WriteLine(ws.GetOrderByRef("ABC123").Requested_By);
Thread.Sleep(5000);
}
catch (Exception ex)
{
Console.WriteLine(ex);
Thread.Sleep(500000);
}
}
** Solved.
This issue was a parameter I left out for brevity was actually the cause, it wasn't serialised and thus rejected.

The cause was another parameter "Request_Items" which wasn't serialised with DataContract in its class.

Related

WCF Client with ChannelFactory, method returns ProtocolException / 405 Method not Allowed

I am writing a part of the program, which is used for communication between client and server.
Service only forwards the query to the database. But when I try to send a query I get an exception "ProtocolException / (405) Method not allowed".
I tried answers from ProtocolException Unhandled/(405) Method not allowed with WCF; Bindings and Endpoints look right though, but nothing helped.
Here are some of my files:
Client for communication It is library, because we want to use it from Unity and I also want this code in tests.
namespace Client
{
public class ClientCommunicationWcf : IDisposable
{
private readonly ChannelFactory<ITask> _taskFactory;
public ClientCommunicationWcf()
{
_taskFactory = new ChannelFactory<ITask>("localhost");
}
public T GetResponse<T>(string commandName, object data)
{
var channel = _taskFactory.CreateChannel();
channel.Execute(commandName, data);
return (T)channel.ResponseObject;
}
public void Dispose()
{
_taskFactory.Close();
((IDisposable) _taskFactory).Dispose();
}
}
}
DataContract
namespace CommunicationCommonLib.Requests
{
[DataContract]
[KnownType(typeof(LoginUserRequest))]
public class LoginUserRequest
{
[DataMember]
private readonly string _username;
[DataMember]
private readonly string _password;
public LoginUserRequest(string username, string password)
{
_username = username;
_password = password;
}
public string Username
{
get { return _username; }
}
public string Password
{
get { return _password; }
}
}
}
ServiceContract
namespace CommunicationCommonLib
{
[ServiceContract]
public interface ITask
{
object ResponseObject
{
[OperationContract]
get;
}
/// <param name="data"></param>
[OperationContract]
void Execute(string commandName, object data);
}
}
Service:
IServerTask is child of ITask
namespace WcfService2
{
public class ServerTaskService : IServerTask, ITask
{
private object _responseObject;
public object ResponseObject
{
get { return _responseObject; }
}
public void Execute(string commandName, object data)
{
DataCommands.RunCommand(commandName, data, this);
}
public void SetResponse(object response)
{
_responseObject = response;
}
}
}
Web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WcfService2.ServerTaskServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="WcfService2.ServerTaskServiceBehavior" name="WcfService2.ServerTaskService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding" contract="CommunicationCommonLib.ITask" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="01:00:00" sendTimeout="04:00:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="209715200" maxBufferSize="52428800" maxReceivedMessageSize="52428800"
textEncoding="utf-8" transferMode="Streamed" useDefaultWebProxy="false"
messageEncoding="Mtom">
<readerQuotas maxStringContentLength="10485760" maxArrayLength="52428800" />
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<client>
<endpoint address="http://localhost:55555/Task" binding="basicHttpBinding" contract="CommunicationCommonLib.ITask" name="localhost"/>
</client>
</system.serviceModel>
</configuration>
Address "http://localhost:5555/Task" is also set in WcfService2 - Properties - Web, where it is used IIS Express.
I wrote WPF application for testing client server communication, where is stored App.config. WPF is only for sending request and checking the result.
Web.config may be wrong, because it is my first WCF and I tried different things from examples.
When I run program, browser open "http://localhost:5555/Task", so I think that service is running.
Thanks for help.
EDIT: ServerTaskService is child of IServerTask and ITask.
Your service contract name is ITask while your service class implements some different interface i.e. IServerTask. Please correct service class definition.

Not Getting the Data in URL by Web Service

I am making web service and not getting the parse data through URL
Code of WEB SERVICE is this. my IService class
namespace DataService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedResponse)]
List<RequestData> GetUser(RequestData data);
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "UsersList/{id}", RequestFormat = WebMessageFormat.Json)]
RequestData UsersList(string id);
}
[DataContract]
public class RequestData
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Address { get; set; }
}
}
this is my service1 class inherited by Iservice1 Class
namespace DataService
{
public class Service1 : IService1
{
public List<RequestData> GetUser(RequestData data)
{
List<RequestData> list = new List<RequestData>();
if (data.Name.ToUpper() == "MAIRAJ")
{
list.Add(new RequestData
{
Name = "Mairaj",
Age = 25,
Address = "Test Address"
});
list.Add(new RequestData
{
Name = "Ahmad",
Age = 25,
Address = "Test Address"
});
list.Add(new RequestData
{
Name = "Minhas",
Age = 25,
Address = "Test Address"
});
}
return list;
}
public RequestData UsersList(string userId)
{
if (userId == "1")
{
return new RequestData
{
Name = "Mairaj",
Age = 25,
Address = "Test Address"
};
}
else
{
return new RequestData
{
Name = "Amir",
Age = 25,
Address = "Test Address"
};
}
}
}
}
I am giving this URL after deploying web service http://116.58.61.180/ADG/Service1.svc
what Exact url should parse to get the data
this is my web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I think you just forgot few things in your web.config :
<endpointBehaviors>
<behavior>
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
And
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
If you don't put all this stuffs in your web.config you won't be able to get your services working.
The full Web.config would be like this :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
For more details I had written few months ago a post on my blog about WCF and REST :
Simple WCF and REST service
WCF and POST method
Follow these steps:
Decorate your service class with follwing attribute
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
Web.config should look like this
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>
Your Global.asax should look like this.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
// Edit the base address of Service1 by replacing the "Service1" string below
RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)));
}
}

WCF exception IErrorHandler not getting called

I seem to be having a problem for getting IErrorHandler interface to work. My code is
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace WcfService3
{
public class Service1 : IService1
{
public string GetData(int value)
{
throw new Exception("asdf");
}
}
public class MyErrorHandler : IErrorHandler
{
public MyErrorHandler()
{
string Hello = "";
}
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
var vfc = new MyFault();
var fe = new FaultException<MyFault>(vfc);
var fault = fe.CreateMessageFault();
msg = Message.CreateMessage(version, fault, "http://ns");
}
}
public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior
{
public override Type BehaviorType
{
get { return GetType(); }
}
protected override object CreateBehavior()
{
return this;
}
private IErrorHandler GetInstance()
{
return new MyErrorHandler();
}
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandlerInstance = GetInstance();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(errorHandlerInstance);
}
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
{
if (endpoint.Contract.Name.Equals("IMetadataExchange") &&
endpoint.Contract.Namespace.Equals("http://schemas.microsoft.com/2006/04/mex"))
continue;
foreach (OperationDescription description in endpoint.Contract.Operations)
{
if (description.Faults.Count == 0)
{
throw new InvalidOperationException("FaultContractAttribute not found on this method");
}
}
}
}
}
}
My web.config is:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="WcfService3.Service1">
<endpoint address=""
binding="basicHttpBinding"
contract="WcfService3.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="errorHandler"
type="WcfService3.ErrorHandlerExtension, WcfService3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
My WCF interface is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService3
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(MyFault))]
string GetData(int value);
}
[DataContract]
public class MyFault
{
}
}
My question is in IErrorHandler in WCF, if there is any exception during the WCF service call, the HandlerError() function is suppose to get called first like the C# windows application UnhandledException class and then the service should crash right? In the code above, during the service call, an exception is thrown but my HandlerError function is not getting called before the exception is thrown? My goal is to log the error and the WCF service can throw the unhandled exception and crash. I was expecting during the debugging that the breakpoint will visit the HandleError function, but that function is not getting called and just an exception shows up?
Aren't you missing <errorHandler /> in your behavior section?
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<!-- HERE -->
<errorHandler />
<!-- HERE -->
</behavior>
The full answer is here. Plus 1 to that answer.
In case anyone else comes across this, when I ran across this error, it was because the error was getting thrown in a method that was called from some LINQ expression. The method wasn't actually called until WCF tried to serialize the response, which then threw outside of the service scope. WCF won't pass these errors to the IErrorHandler.
Materializing the list before returning using .ToList() solved this problem for me.

WCF method returning JSON / XML objects not working

I was new to WCF, i was trying to build a sample application using VS 2010 and code provided below
IProductService.cs
[ServiceContract]
public interface IProductService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
Products SelectAllProducts();
}
[DataContract]
public class Product
{
[DataMember]
public int ProductId { get; set; }
[DataMember]
public string Name { get; set; }
}
[CollectionDataContract]
public class Products : System.Collections.ObjectModel.Collection<Product>
{
}
ProductService.cs
public class ProductService : IProductService
{
public Products SelectAllProducts()
{
var products = new Products();
var prod = new Product();
prod.ProductId = 1;
prod.Name = "SAMSUNG";
products.Add(prod);
prod = new Product();
prod.ProductId = 2;
prod.Name = "RELIANCE";
products.Add(prod);
return products;
}
}
http://localhost:1050/WCFService1/ProductService.svc/SelectAllProducts
Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
and if try using the above url blank is getting displayed can some one help me ???
thanks in advance ..
Do some change in interface
[ServiceContract(Namespace = "JsonpAjaxService")]
interface IService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
method()
}
add some code on class like below
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService
your web.config file like this
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="None" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint name="" crossDomainScriptAccessEnabled="true"/>
</webScriptEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>
I don't see the service binding the web.config. Try adding line such as below:
<services>
<service name="[Your Namespace].ProductService">
<endpoint address="" binding="webHttpBinding" contract="[Your Namespace].IProductService" />
</service>
</services>
Its important that you use webHttpBinding for REST WCF Services. Also you need to attach webHttpBehavior - that's possible by using WebServiceHostFactory in your svc file. For example,
<%#ServiceHost Language="C#" Service="[YourNameSpace].ProductService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
See below for more info:
http://saravananarumugam.wordpress.com/2011/03/04/simple-rest-implementation-with-webhttpbinding/
http://msdn.microsoft.com/en-us/magazine/dd315413.aspx

svcutil.exe or testing wcf service JSON ouput?

this post is off the back of my last question (thought i'd start a new question).
i am trying to create and test a simple (simple to you not me lol) WCF web service that outputs JSON. I beleive (with help) the application is ok but i need to test it and i a not sure how.
I'll attach my code below but here is what is happening, if i run the application it loads http://localhost:52002/ and i get the welcome to ASP.NET page, if run the application while i am in my .svc it loads http://localhost:52002/MyTestService.svc and i get the page:
You have created a service.
To test this service, you will need to create a client and use it to
call the service. You can do this using the svcutil.exe tool from the
command line with the following syntax:
svcutil.exe http://localhost:52002/MyTestService.svc?wsdl
I have been told i can http://localhost:52002/MyTestService.svc/GetResults to see the JSON output (see code below) but all i get is:
The webpage cannot be found
Any suggestions would be great, i apologies now for being abit new to all this and please ask you to maybe spell things out abit more then you normally would lol
Here is my code and tanks very much
Person.cs
[DataContract]
public class Person
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public int Age { get; set; }
public Person(string firstName, string lastName, int age)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
}
}
MyTestServices.svc.cs
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = `AspNetCompatibilityRequirementsMode.Allowed)]`
public class TestService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public List<Person> GetResults()
{
List<Person> results = new List<Person>();
results.Add(new Person("Peyton", "Manning", 35));
results.Add(new Person("Drew", "Brees", 31));
results.Add(new Person("Tony", "Romo", 29));
return results;
}
MyTestService.svc
<%# ServiceHost Language="C#"
Service="TestService.TestService"
Factory="System.ServiceModel.Activation.ServiceHostFactory" %>
Web.Config
<configuration>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<bindings />
<client />
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
I always use fiddler to debug the request. With the new Web Api for WCF you can set the accept header for the client to application/JSON and the response will be formatted as JSON.
I am not a WCF expert, so I cannot tell you what is wrong with your current application, but I can give you instructions for setting up a very simple example using your code, which will return a result in Fiddler.
Create a new ASP.NET Empty Web Application
Add a code file with the following:
Normally I wouldn't put everything in one file, but for simplicity...
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace WebApplication1
{
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
List<Person> GetResults();
}
public class TestService : ITestService
{
public List<Person> GetResults()
{
List<Person> results = new List<Person>();
results.Add(new Person("Peyton", "Manning", 35));
results.Add(new Person("Drew", "Brees", 31));
results.Add(new Person("Tony", "Romo", 29));
return results;
}
}
[DataContract]
public class Person
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
[DataMember]
public int Age { get; set; }
public Person(string firstName, string lastName, int age)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
}
}
}
Update the web.config file:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="test.svc"
service="WebApplication1.TestService"
factory="System.ServiceModel.Activation.WebServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
</configuration>
You don't need a .svc file, so start the application, making note of the root url used by the ASP.NET Development Server. On the Request Builder tab of fiddler enter your url:
Click the Execute button and you should see your service results:
Hopefully you can use this to figure out what you need to update on your service to get it running. Good luck!
I do not see your interface, but you are missing some stuff if you want it to be rest.
//Add this to your method
[WebGet(UriTemplate="/Results")]
public List<Person> GetResults()
{
List<Person> results = new List<Person>();
results.Add(new Person("Peyton", "Manning", 35));
results.Add(new Person("Drew", "Brees", 31));
results.Add(new Person("Tony", "Romo", 29));
return results;
}
Now you should be able to call it using http://localhost:52002/MyTestService.svc/Results. Just change the uri tempalte to what you want it to be.
You may also need to change the factory to be the WebServiceHostFactory.
<%# ServiceHost Service="TestService.MyTestService"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Categories