Service Only Works While Debugging - c#

I have created a WCF service and am having some trouble testing it once it has been deployed. Here is the PowerShell I am using to test it:
$service = New-WebServiceProxy -Uri http://localhost:16651/Service.svc
$service.GetList()
When debugging the service from Visual Studio with F5, I can call this script without any issue. GetList() returns a long list of telephone numbers.
However, when I host the site on IIS and run the above script, I get an empty return value.
Service Factory
So following this question, I added this attribute to Service.svc:
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"
However, this resulted in my script returning an error on the first line:
New-WebServiceProxy : Object reference not set to an instance of an object.
Which does not make any sense to me, as I am not referencing any empty objects... (this error appears when debugging and when hosting over IIS).
Web.Config
Next, I tried updated my web.config as per the linked question:
<services>
<service name="LyncWebService.Service">
<endpoint binding="webHttpBinding" contract="LyncWebService.IService" behaviorConfiguration="web"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
However, now when I try to run my PowerShell script I get this error both during debugging and when hosting on IIS (again on the first line):
The HTML document does not contain Web service discovery information.
I am totally lost here and have no idea what is going wrong. I suspect it is to do with my config file, as it did seem to work when debugging from VS before I messed with the configuration.
Any help or guidance is much appreciated - and please let me know if I can provide any other information or test anything.
Here is the code that makes up my service currently:
Service.svc.cs
namespace LyncWebService
{
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke]
List<string> GetList();
}
public class Service : IService
{
public List<string> GetList()
{
return Ps.GetAssignedNumbers(#"
Set-ExecutionPolicy RemoteSigned
Import-Module Lync
$(Get-CSUser).LineUri"
);
}
}
}
Web.Config
<?xml version="1.0"?>
<configuration>
<appSettings/>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime/>
</system.web>
<system.serviceModel>
<services>
<service name="LyncWebService.Service">
<endpoint binding="webHttpBinding" contract="LyncWebService.IService" behaviorConfiguration="web"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<!--<add binding="basicHttpsBinding" scheme="https"/>-->
<add binding="webHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" 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>

Thanks to Jonathan Coffey, I realised that the service was being run by the LocalSystem account.
After changing this to my own user account and hosting the original web.config on IIS, I am now able to retrieve the full list using my PowerShell script.
Open IIS
Application Pools
Right-Click the Application pool
Advanced Settings...
Process Model -> Identity
Custom Account (Don't forget to include the domain for the User Name!)

Related

Attaching WCF DLL to existing Website

Okay I've created a WCF which I have tested in in IIS and works correctly.
There is a website running, and I've done the following to add this service to that domain:
-Copied the WCF DLL into the website's bin folder.
-Also copied all the DLL this service uses. (Just Newtonsoft.Json)
-Created a new .svc with the following line:
<%# ServiceHost Language="C#" Debug="true" Service="wcfOnScore.OnScoreQuery"%>
-And also added the following to the website's web.config file:
<System.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WithDebug">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
<services>
<service name="wcfOnScore.OnScoreQuery">
<endpoint address="http://www.onscore.co.za/OnScoreQuery.svc"
binding="basicHttpBinding"
listenUri="/"
contract="wcfOnScore.IOnScoreQuery" />
</service>
</services>
</system.serviceModel>
Now this seems to be working. I get the following page when I open it in the browser:
Link To The Screenshot
It is however, not working sadly. I am trying to consume this service from a c# Xamarin android application. It is supposed to return a JSON string. And does this fine when it is hosted locally - This leads me to believe the problem is not in the WCF but the way I am trying to host it.
Anything I might have missed? Or any other alternatives?
Thanks in advance people.
EDIT:
Thought I'd include the error.
"System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation."
The is what the completed eventhandler arguments returns.
Well this an answer to why I get the error, not really a solution. (Yet)
I commented out the Newtonsof.Json using statement. And put in a simple text return which worked.
So from this I deduce that the WCF code can't get its hands on the json.dll.
So it looks like all the above was done correctly if you would like to use as reference. (Except that .dll off course).
If you are trying to return JSON first test it on browser. Your service is SOAP based service because you are using basicHttpBinding. To get result on browser change the binding to WebHttpBinding and add following in your web config.
<endpointBehaviors>
<behavior name="RestBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
If you are able to get response on the browser, you will get response through android also.

IIS hosted WCF Service return HTTP 400 Bad Request

I have been searching for hours, but I could not find the solution. I will explain briefly.
I am learning WCF Services. I have just created a service and browse it. Here is the config file:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="EmployeeServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="EmployeeServiceBehaviour" name="EmployeeConfiguration">
<endpoint address="http://localhost:2005/EmployeeService.svc" binding="basicHttpBinding"
bindingConfiguration="" contract="IEmployeeConfiguration" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
When browse it from Visual Studio there seems no problem. It works perfectly.
Second, I am trying to publish it on IIS. What I am doing is this:
I publish the service to a folder and add this service to IIS.
I select port 3006 as a port.
Below its config file. Note that I also changed port inside config to 3006
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="EmployeeServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="EmployeeServiceBehaviour" name="EmployeeConfiguration">
<endpoint address="http://localhost:3006/EmployeeService.svc" binding="basicHttpBinding"
bindingConfiguration="" contract="IEmployeeConfiguration" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
And I am waiting to run smoothly but:
IIS gives me a blank page from Chrome
And HTTP 400 Bad Request from Explorer
Lastly, if I remove address part from config file everything works well. But other confused thing is that, on my other computer after above scenario(address provided) I can reach the service. So, I really tired of searching why this is working on one computer and not working on another one. Could someone explain it to me?
I know it is a bit longer, but I have to explain it clearly.
Thanks
According my searches, I should not provide an address.
msdn.microsoft.com/en-us/library/aa751792(v=vs.110).aspx
You must always use relative endpoint addresses for IIS-hosted service
endpoints. Supplying a fully-qualified endpoint address (for example,
localhost/MyService.svc) can lead to errors in the deployment of the
service if the endpoint address does not point to the IIS-application
that hosts the service exposing the endpoint. Using relative endpoint
addresses for hosted services avoids these potential conflicts.
I think this will solve your problem:
Add this endpoint to your service:
<endpoint address="mex" binding="mexHttpBinding"
bindingConfiguration="" contract="IMetadataExchange" />
And change the name attribute of the service to your service class's full name:
<service behaviorConfiguration="EmployeeServiceBehaviour"
name="Namespace.EmployeeConfigurationClass">
Hope that is enough
This may be of help. ive just spent over 2 hours trying to get this working. i use FF and its set as the default browser.
in FF it was adding a / on the end of my URL
http://services.tester.dev/VehicleFeedService.svc/
which returned a NetworkError: 400 Bad Request
however in IE or chrome, it doesnt put the / on the end and it works fine.
one thing to note.. even in FF which was giving me a 400 bad request, the ?wdsl did work
http://services.tester.dev/VehicleFeedService.svc?wsdl
it appears that the / was causing the issue
You can try fiddler and also try the svcTracer which may give you lot of debugging information on the top of it you can also use includeExceptionDetailInFaults=true flag on the server but its important to flag that its not always right to send this information to the client specially if client is an external entity. With this warning following is the hint how to use it.
<serviceBehaviors>
<behavior name="ServiceBehavior">
....
<serviceDebug includeExceptionDetailInFaults="true" />
....
</behavior>
</serviceBehaviors>
Happy debugging :)

Localhost WCF service unavailable after stopping debug

I have problem reaching my WCF service on localhost. When I start it from Visual Studio, everything is fine. However, as soon as I stop debugging it, the service is no longer available. This is odd, because it happens only with projects created by myself. When I download a solution (e.g. this one), everything is just fine and the service is available also after I stop debugging it.
Thus, I suppose, it is a configuration problem. However, I am not able to find it. Here is my Web.config file:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name ="svcbh">
<serviceMetadata httpGetEnabled="False"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name ="DuplexServer.CalculatorService" behaviorConfiguration ="svcbh" >
<host>
<baseAddresses>
<add baseAddress = "http//localhost:3435/CalculatorService/" />
</baseAddresses>
</host>
<endpoint name ="duplexendpoint"
address =""
binding ="wsDualHttpBinding"
contract ="DuplexServer.ICalculatorDuplex"/>
<endpoint name ="MetaDataTcpEndpoint"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
It sounds like the settings for your solution/project is not what you desire. Go the properties of your WCF project and look at "Web" settings(plenty of information on the net about this)
You will probably need to change from "Use Visual Studio Development Server" to "Use local IIS Web Server"
Assuming you are using IIS Express, it's usually caused by Edit and Continue (Right click the project, select properties. It's a checkbox in the Web tab).
Disable this, and the service should keep running when you stop debugging.
On a related note, if you wish to simply start the service to have available (i.e. you don't want to debug, you just want it running), you can use "Start without Debugging" in the Debug menu (CTRL + F5 by default)

WCF Error - Method Not Allowed

When running the WCF test client and debugging the WCF service locally, everything works fine. After I deploy it to IIS on a remote server and then try loading it with the WCF test client I start getting "Object not set to an instance of object" errors. I added a try-catch to the service and the error changed to "Method not allowed".
I have been reading up on these errors all day and most posts relate to people using JSON or AJAX to access their WCF client. I have tried many of the suggested solutions, most of which were changes to web.config. I am simply accessing it using the test client at this stage, it will be consumed by a Winform application once proven to work.
The 2 methods exposed on the service both create connections to a SQL server on a different domain, although there is a trust set up. I am thinking this could be part of the problem.
My Service Interface
[ServiceContract]
public interface IMeterQueryService
{
[OperationContract]
List<Meter> FindMeter(string mprn);
Implemented Service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MeterQueryService : IMeterQueryService
{
public List<Meter> FindMeter(string mprn)
{
using (var da = new DataAccess())
{
var meters = da.GetMeter(mprn);
da.Dispose();
return meters;
}
}
App Config File
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<connectionStrings>
<add name="Tims" connectionString="hidden" providerName="System.Data.SqlClient"/>
</connectionStrings>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="TimsAPI.MeterQueryService">
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false 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="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
web config file, site references the WCF service library.
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="false" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="TimsAPI.MeterQueryService">
<endpoint address="http://easvr33:1000/" binding="basicHttpContextBinding" bindingConfiguration=""
contract="TimsAPI.IMeterQueryService" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="localhost" />
</baseAddresses>
</host>
</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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="false" />
</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>
Update
I recreated the WCF service as a WCF Service website, rather than a library and it all works now. Something weird between the 2 config files I think. I would still be interested to know why it never worked but I do also understand it may be hard to diagnose for someone without full access to the source
When a WCF service is hosted via an IIS website the service app.config is not used and instead the hosing site's web.config is loaded. All settings needed for the service to work must be duplicated to the web.config of the hosting site.
Might be an issue with serving the SVC to begin with. From here:
1.Open your Virtual Directory’s Properties.
2.Go to the Directory tab.
3.Click Configuration.
4.Click Add…
5.Provide the following information:
a.Executable: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
b.Extension: .svc
c.Verbs: GET,HEAD,POST,DEBUG

Displaying WCF Web service operations

So I've created a WCF service application and hosted it on IIS7. It currently has a few test 'helloworld' methods. When I run it in my browser I get this screen:
Now the service itself works great, but how can I display the operations like this:
Thanks to marc_s for the link: http://www.dotnetcurry.com/ShowArticle.aspx?ID=399 which I've followed so my web config is now setup like:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfServer.Service1">
<endpoint address="" binding="webHttpBinding" contract="WcfServer.IService1" behaviorConfiguration="HelpBehaviour" />
</service>
</services>
<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>
<endpointBehaviors>
<behavior name="AjaxBehavior">
<enableWebScript />
</behavior>
<behavior name="HelpBehaviour">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" showFlags="Date, Time, Size, Extension" />
</system.webServer>
</configuration>
However, this only works locally. When I publish to my server on IIS7 I get a 404 error page when I click on the help link. Does anyone know why this is, or has come across it before?
(Last bit was solved by running: aspnet_regiis.exe -iru)
If you have a WCF service with a SOAP binding, you're unfortunately out of luck: there's no way in WCF out of the box to get a listing similar to ASMX with all the services.
With REST binding (webHttpBinding) and .NET 4.0, you can have an automatic help page generated which lists the URI templates, the HTTP methods supported and so forth. You can also tweak that page to a certain degree.
In order to have that automatic help page generated, you need to define (and reference) an endpoint behavior:
<behaviors>
<endpointBehaviors>
<behavior name="HelpBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
Then reference that behavior from your webHttpBinding endpoint, and you're done.
Read all about it:
A Developer's Introduction to Windows Communication Foundation 4
Windows Communication Foundation 4.0 - New REST Features
Clients and the Automatic Help Page in WCF WebHttp Services

Categories

Resources