My RESTUL WCF doesn't work properly - c#

I have the followings:
In Competitions.svc:
<%# ServiceHost Language="C#" Debug="true" Service="MySite_WebSite.Pages.Client.CompetitionsSVC" CodeBehind="Competitions.svc.cs" %>
In ICompetitions.cs :
namespace MySite_WebSite.Pages.Client
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICompetitions" in both code and config file together.
[ServiceContract(Name="CompetitionsSVC")]
public interface ICompetitions
{
[OperationContract]
[WebInvoke(
Method = "GET"
, RequestFormat = WebMessageFormat.Json
, ResponseFormat = WebMessageFormat.Json
, UriTemplate = "DoWork"
, BodyStyle=WebMessageBodyStyle.Wrapped
)]
Dictionary<DateTime, List<Competitions.Entry>> DoWork();
}
}
In Competitions.svc.cs :
namespace MySite_WebSite.Pages.Client
{
[DataContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class CompetitionsSVC : ICompetitions
{
#region ICompetitions Members
public Dictionary<DateTime, List<Competitions.Entry>> DoWork()
{
var c = new Competitions();
return c.GetMonthlyEntries(new Competitions.ParamGetMonthlyEntries()
{
Start = DateTime.Now.Date.AddMonths(-1)
, End = DateTime.Now.Date.AddMonths(2)
, UserLang = "fr-BE"
, ActiveLang = "fr-BE"
, IsExternal = false
});
}
#endregion
}
}
In Web.config:
<system.serviceModel>
<services>
<service name="MySite_WebSite.WS.WCF.SubsetMID">
<endpoint address=""
binding="wsHttpBinding"
contract="MySite_WebSite.WS.WCF.ISubsetMID" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
<service name="MySite_WebSite.Pages.Client.CompetitionsSVC">
<endpoint address=""
binding="webHttpBinding"
behaviorConfiguration="WebBehavior"
contract="MySite_WebSite.Pages.Client.ICompetitions" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding>
<security mode="None"/>
</binding>
</wsHttpBinding>
<netTcpBinding>
<binding name="NetTcpBinding_IServiceWCallBack" sendTimeout="00:10:00"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" />
<security mode="None" />
</binding>
<binding name="NetTcpBinding_IHandleSubset">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment
multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true"
/>
</system.serviceModel>
When I enter the url
localhost2/MySite_WebSite/Pages/Client/Competitions.svc/DoWork
, it doesn't work.
I have a breakpoint at the begining of the method, and I can see the method gets called twice, yet it doesn't return anything (I don't even think it send any HTTP code backs).
What did I do wrong?
Additional notes:
Entry is actually a "base class".
public class EntryCompetition : Entry
public class EntryEvent : Entry
In my code the dictionary actually contains EntryCompetition and EntryEvent instances.

Thanks for posting your code that definitely helps. But i think you're going to need to show a little more work, and some more concrete results on how your project is failing. But so as not to leave you helpless. I recommend looking at Fiddler
http://www.telerik.com/fiddler
It allows you to create Http requests and to see the responses inside of it's console. it is useful for seeing specifically what http response code your endpoint is returning, and allows you to modify your request through the composer window.
another helpful tip, would be to step all the way through your code, so you can point us to exactly what line is failing or what values are being set before your method completes.
Without more information, my best guess is you're code is throwing and most likely swallowing an exception. Or your methods or calls are setting null values that don't return the values you expect. Please reply once you've setup some further tests and updated your question if you are still having issues.

Ok, I solved the problem. I use a custom piece o code to serialize the dictionnary into a JSON string and I don't use DateTime objects as keys anymore.

Related

Same WCF service with different EndPoints and Different Bindings For HTTPS

I have looked at several posts on SO which are showing how to add multiple endpoints for same service, but non of them is actually using HTTPS, which is why I am asking this question.
What I have
I have a web service,
https://portal.gov.com/us/216/_vti_bin/external/gov.svc
What I want
I want to call this web services using two different configurations, and bindings with different ENDPOINTS but SAME URL ?. (Sorry maybe I am confused with concept of EndPoints)
Here is what my web.config looks like,
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Gov_ServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="Gov_webHttpBinding">
<security mode="Transport">
<transport clientCredentialType="InheritedFromHost" />
</security>
</binding>
</webHttpBinding>
<!--<basicHttpBinding>
<binding name="Gov_BasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="InheritedFromHost" />
</security>
</binding>
</basicHttpBinding>-->
</bindings>
<services>
<service name="Portal.WebServices.External.Gov" behaviorConfiguration="Gov_ServiceBehavior">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="restBehavior" contract="Portal.WebServices.External.IGov" bindingConfiguration="Gov_webHttpBinding"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
<!--<endpoint address="basic" binding="basicHttpBinding" contract="Portal.WebServices.External.IGov" bindingConfiguration="Gov_BasicHttpBinding"/>-->
</service>
</services>
</system.serviceModel>
</configuration>
WHERE IS THE PAIN
IT only works until I keep basicHttpBinding commented out and it's endpoint, as soon as I include it, I get silent error.
According to this - https://msdn.microsoft.com/en-us/library/ms751515(v=vs.110).aspx
It should work, but it doesn't maybe because I am using HTTPS and adding BINDINGS tag to my web.Config
What you are trying to achieve is impossible. You can't apply two different bindings with exactly the same Endpoint. If you try to read again your reference here it is clear that the sample has two different endpoints :
First address is http://localhost/servicemodelsamples/service.svc and the second
is http://localhost/servicemodelsamples/service.svc/secure. These two endpoints are different to each other but share with same contract.
The second endpoint is just relative to the base address http://localhost/servicemodelsamples/service.svc.
I hope this make your mind clear about binding and endpoint.

WCF RESTful Calling Issue in Visual Studio 2013

I have an ASP.NET application which has been around since the ASMX days. When I upgraded this project in the past, I was able to utilize a WCF service by extending the System.Web.Services.WebService class and then utilize WebInvoke attributes to allow for RESTful calls to my various methods. Here is an example:
[ServiceContract(Namespace = "http://10.23.41.189/", Name = "SEO")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SEO : System.Web.Services.WebService
{
[WebMethod(Description = "Use this Web Method to log into The SEO Panel")]
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Login?User={User}&Pass={Pass}")]
public string Login(string User, string Pass)
{
That method would then be called without issue by going to http://10.23.41.189/seo.svc/login?User=USER&Pass=PASS
In the old project, I was using a web site project not a web application and now that I have upgraded to Visual Studio 2013, I am using a web application - and that call no longer works. I literally ported everything over using copy and paste, when I run the WSDL, I see the methods, but all calls come back with a 400 Bad Request error. Here is my web.config information:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="SEO">
<endpoint address="http://10.23.41.189/SEO.svc" behaviorConfiguration="json" binding="webHttpBinding" name="MainHttpPoint" contract="SEOPlatform.Intranet.SEO"/>
<endpoint address="mex" binding="mexHttpBinding" name="MexEP" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://10.23.41.189/SEO.svc"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<webHttpBinding>
<binding openTimeout="00:10:00" sendTimeout="00:10:00" useDefaultWebProxy="false">
<readerQuotas maxDepth="32" maxStringContentLength="2048000" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="json">
<webHttp helpEnabled="false" automaticFormatSelectionEnabled="false" defaultBodyStyle="Bare"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpGetBinding="webHttpBinding" httpGetBindingConfiguration=""/>
<serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" includeExceptionDetailInFaults="true"/>
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="http" port="80"/>
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I know that I am missing something but I cannot figure it out - does anybody have any ideas?
Thank you!
I swear I should have just waited - I often write questions here and then the related questions always has the answer I need. This time that did not happen but, as I entered the web.config data, I discovered the issue. Rather than delete this question, I figured I would post an answer to hopefully help others.
The problem was with the service name:
<services>
<service name="SEO">
With a web site project, the rules are lax but a web application requires the proper notation. All I did was change this to:
<services>
<service name="SEOPlatform.Intranet.SEO">
And that fixed the issue. I also changed the multipleSiteBindingsEnabled to false but if you need that to be true there are great answers already posted elsewhere on this site.

How to call a service using multiple Endpoint URIs

To put into context, I have a client application that will attempt to call a webservice that will be deployed on multiple web servers. The URI list will be obtained from the Settings.settings file of the client and a foreach loop will cycle through the URIs until the available service responds.
Let's say I have a service with the following contract:
[ServiceContract]
public interface ICMMSManagerService
{
[OperationContract]
ServerInfo GetServerInfo(string systemNumber);
}
In the web.config of the service's project, I have defined CMMSManager service with the the endpoint name: BasicHttpBinding_IWorkloadMngrService
<system.serviceModel>
<services>
<service name="WorkloadMngr">
<endpoint binding="basicHttpBinding" contract="IMetadataExchange" />
</service>
<service name="CMMSManager">
<endpoint binding="basicHttpBinding" contract="IMetadataExchange" name="BasicHttpBinding_IWorkloadMngrService" />
</service>
</services>
<client>
<remove contract="IMetadataExchange" name="sb" />
</client>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
On the client side, I have the following code executed when the application starts:
private void QueryWebServiceUrls()
{
var webServiceUrls = Properties.Settings.Default.WebServiceUrls;
foreach (var webServiceUrl in webServiceUrls)
{
try
{
var client = new CMMSManagerServiceClient("BasicHttpBinding_IWorkloadManagerService");
client.Endpoint.Address = new EndpointAddress(new Uri(webServiceUrl),
client.Endpoint.Address.Identity, client.Endpoint.Address.Headers);
client.Open();
var result = client.GetServerInfo("test");
}
catch (EndpointNotFoundException e)
{
continue;
}
catch (InvalidOperationException e)
{
break;
}
}
}
But the application crashes with an InvalidOperationException when the CMMSManagerServiceClient class is instanciated.
Could not find endpoint element with name
'BasicHttpBinding_IWorkloadMngrService' and contract
'ComClientService.ICMMSManagerService' in the ServiceModel client
configuration section. This might be because no configuration file was
found for your application, or because no endpoint element matching
this name could be found in the client element.
I have the following configuration in the app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICMMSManagerService">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/WorkloadMngr/CMMSManagerService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICMMSManagerService"
contract="ComClientService.ICMMSManagerService" name="BasicHttpBinding_ICMMSManagerService" />
</client>
</system.serviceModel>
I thought everything was valid by passing the BasicHttpBinding_ICMMSManagerService parameter to the CMMSManagerServiceClient class. I have no clue what am I missing at the moment... Any ideas?
The error is telling you exactly what's wrong: there is no endpoint with the name BasicHttpBinding_IWorkloadMngrService. The app.config says the endpoint is called BasicHttpBinding_ICMMSManagerService so your code should be:
var client = new CMMSManagerServiceClient("BasicHttpBinding_ICMMSManagerService");
Hope this helps.

WCF service method call time grows

Setup is mono latest stable on raspberry pi, polling data from service on server with .NET 4.5.
My configuration for server side:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="vlcBehaviour">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ser.Serwys">
<endpoint address="net.tcp://192.168.56.1:9070/WindowService" binding="netTcpBinding" bindingConfiguration="AnonymousTcpBinding"
contract="Window.Service.IWindowServiceHost" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="AnonymousTcpBinding" receiveTimeout="00:00:01"
sendTimeout="00:00:01"
maxBufferSize="1000"
maxConnections="100"
maxBufferPoolSize="100"
listenBacklog="200"
maxReceivedMessageSize="1000">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
On client side:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="maxItems">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="AnonymousTcpBinding" openTimeout="00:00:01" receiveTimeout="00:00:01" sendTimeout="00:00:01" maxBufferSize="1000" maxConnections="200" listenBacklog="200" maxReceivedMessageSize="1000">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint name="WindowService" address="net.tcp://192.168.56.1:9070/WindowService" binding="netTcpBinding" bindingConfiguration="AnonymousTcpBinding" contract="Window.Service.IWindowServiceHost" />
</client>
</system.serviceModel>
Service contract:
namespace Window.Service
{
[ServiceContract(
Namespace = "http://window",
Name = "WindowHost")]
public interface IWindowServiceHost
{
[OperationContract]
void Connect(int windowId);
[OperationContract]
void Disconnect();
[OperationContract]
DisplayData GetData();
}
}
Implementation of service:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class Serwys:IWindowServiceHost
Method that is called:
public DisplayData GetData()
{
Console.WriteLine("Called get data {0}:{1}:{2}",DateTime.Now.Minute,DateTime.Now.Second,DateTime.Now.Millisecond);
return new DisplayData
{
BoxesInProgress = 1,
};
}
Call to GetData from client takes more and more time, don't know why.
I have tested it on Ubuntu also, Mono is latest version here how I log it:
Stopwatch stp = new Stopwatch();
stp.Start();
var data = remote.GetData();
stp.Stop();
log.WarnFormat("Polling service took: {0} ms", stp.ElapsedMilliseconds);
Any explanations?? I think it is Mono bug, because setup is really basic no concurrency method called is dead simple, and polling times are going up.
I call it on timer elapse, and for test I call it every 10ms but it is growing even if I call it every second, but slower, and this only gives me more time before all crashes.

WCF service returning "is undefined" in JavaScript

When this JavaScript code is run, it tells me that "0x800a1391 - JavaScript runtime error: 'InputService' is undefined".
I have tried and tried, and I just can't seem to figure out of what I am missing...
Web.Config file (just the web service part):
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="CommonEndPointBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service name="InputService">
<endpoint name="" address="" behaviorConfiguration="CommonEndPointBehavior" binding="webHttpBinding" contract="InputService" bindingConfiguration="webBinding" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<!--<security mode="Transport">-->
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
The Service:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class InputService
{
[OperationContract]
public string EditSiteElement(int siteid, string name, string url, string description, int siteorder, bool active)
{
return Input.EditSiteElement(siteid, name, url, description, siteorder, active);
}
}
The references in the web form:
scriptManagerProxy.Services.Add(new ServiceReference("~/User/Input.svc"));
scriptManagerProxy.Scripts.Add(new ScriptReference("~/User/Input.js"));
JavaScript file:
//When edit button is clicked on row.
function EditSiteElement(siteid) {
InputService.GetSiteIdInfo(siteid, function (result) {
var stuff = result.split('ยค');
$('[id$=TextBox_name]').val(stuff[0]);
$('[id$=TextBox_link]').val(stuff[1]);
$('[id$=TextBox_description]').val(stuff[2]);
$('[id$=CheckBox_active]').prop('checked', (stuff[3] == 'True'));
$('[id$=TextBox_order]').val(stuff[4]);
//Open the dialog
$("[id$=panel_Input]").dialog('open');
SiteIdForSave = siteid;
});
}
So, there are a couple of changes you have to do.
First, decorate the service method with the WebInvoke attribute which resides in the System.ServiceModel.Web namespace (you may have to add the reference to your project).
[OperationContract]
[System.ServiceModel.Web.WebInvoke] //add this attribute
public string EditSiteElement(int siteid, string name, string url, string description, int siteorder, bool active)
{
return Input.EditSiteElement(siteid, name, url, description, siteorder, active);
}
Second, in the InputService.svc file (in Visual Studio, right click on the InputService.svc file and select View Markup), add the Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" attribute:
<%# ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" Service="WebApplication6.InputService" CodeBehind="InputService.svc.cs" %>
Make sure that the target framework version for your application is 4.5.
[EDIT]
I suggest you modify the web.config's <system.serviceModel> section as follows. Please pay attention to the use of your namespaces (MyNamespace) and to the fact that I moved the behavior definition from the end point to the service level.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="InputServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service behaviorConfiguration="InputServiceBehavior" name="MyNamespace.InputService">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.InputService" bindingConfiguration="webBinding"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<!--<security mode="Transport">-->
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>

Categories

Resources