wcf REST Ping timeout - wcf

i have set my IIS Authentification = Basic, and create account windows with login = pda and password = xxx.
but when my client acces into my service, i got message timeout
public Stream PingServer()
{
//string LeUrl = "http://localhost:81/Code/WcfService_REST_SuiviColis/WcfService_REST_SuiviColis/Service1.svc";
string LeUrl = "http://xxx.YYY.ZZZ/FA85/Service1.svc/";
string Result = "",ErrPb="";
try
{
var myRequest = (HttpWebRequest)WebRequest.Create(LeUrl);
myRequest.Credentials = new System.Net.NetworkCredential("pda", "xxx");
myRequest.Method = "PUT";
myRequest.ContentLength = 0;
var response = (HttpWebResponse)myRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
// Si le serveur OK
Result = "OK - " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
}
else
{
// Sinon on a le problem
Result = "KO - " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
ErrPb = response.StatusDescription + System.Environment.NewLine;
}
}
catch (Exception ex)
{
// encore un autre problem
Result = "KO - " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
ErrPb += ex.Message + System.Environment.NewLine;
}
when i deleted this code:
myRequest.Credentials = new System.Net.NetworkCredential("pda", "xxx");
myRequest.Method = "PUT";
i got error 401 : Authentification failed
when i deleted this code :
myRequest.ContentLength = 0;
i got error 411 : length required.
but now, i got timeout delayed had expired
and my web.config:
<services>
<service name="WcfService_REST_SuiviColis.Service1" >
<endpoint address="" binding="webHttpBinding" contract="WcfService_REST_SuiviColis.IService1" bindingConfiguration="BasicHttpEndpointBinding" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="BasicHttpEndpointBinding"
maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"
receiveTimeout="00:10:00"
sendTimeout="00:10:00"
openTimeout="00:10:00"
closeTimeout="00:10:00">
<security mode="TransportCredentialOnly" >
<transport clientCredentialType="Basic" />
</security>
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="true">
<serviceActivations>
<add
factory="System.ServiceModel.Activation.WebServiceHostFactory"
relativeAddress="Service1.svc"
service="WcfService_REST_SuiviColis.Service1" />
</serviceActivations>
</serviceHostingEnvironment>

It looks like you are using Windows account against the Basic authentication. You should set IIS authentication with Windows Auth.

Related

Test program just wont invoke service, yet everything looks okay - getting 404 not found

I've created a WCF service to receive data from a sending application. When run, the usual index listing appears:
and clicking on the .svc shows the success page:
So, I've created a basic test form to invoke the methods of the service (there are 2, both are "POST" methods). Since the service methods use JSON & webhttp, I am attempting to invoke the service via an HttpWebRequest.
private void button1_Click(object sender, EventArgs e) {
try {
var request = (HttpWebRequest)WebRequest.Create("http://localhost:54945/Take2ToOffice.svc/ErrorReport");
request.ContentType = "'text/json; charset=utf-8'";
request.Method = "POST";
byte[] chunk = new byte[2048]; //chunk gets initialised, but what it
//contains is mostly irrelevant here
string result = "";
ErrorInfo EI = new ErrorInfo {
Edumis = "9999",
SiteName = "Unknown",
ErrorID = "123",
ContentBlock = chunk
};
string json = new JavaScriptSerializer().Serialize(EI);
//MessageBox.Show(json);
using (var sW = new StreamWriter(request.GetRequestStream())) {
sW.Write(json);
sW.Flush();
sW.Close();
}
var response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream())) {
result = streamReader.ReadToEnd();
}
MessageBox.Show(result);
}
catch (WebException wex) {
string lcResult;
if (wex.Response != null) {
lcResult = "ERROR (web exception, response generated): " + Environment.NewLine;
StreamReader sr = new StreamReader(wex.Response.GetResponseStream());
lcResult += sr.ReadToEnd();
}
else {
lcResult = "ERROR (web exception, NO RESPONSE): " + wex.Message + wex.StackTrace;
}
MessageBox.Show(lcResult);
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
It all seems like pretty basic stuff - especially since I wrote another service very similar to this a few years ago, and my starting point for everything I've done now, was the code I wrote previously - and at this point, I'm just doing this in my development environment.
Yet,
var response = (HttpWebResponse)request.GetResponse();
Returns 404 Not Found. The WebException.Response contains:
{System.Net.HttpWebResponse}
[System.Net.HttpWebResponse]: {System.Net.HttpWebResponse}
base: {System.Net.HttpWebResponse}
ContentLength: 0
ContentType: ""
Headers: {X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcVXNlclxEb2N1bWVudHNcVmlzdWFsIFN0dWRpb1xWaXN1YWwgU3R1ZGlvIDIwMTNcUHJvamVjdHNcVGFrZTJPZmZpY2VDb21tdW5pY2F0aW9uc1xUYWtlMk9mZmljZUNvbW11bmljYXRpb25zXFRha2UyVG9PZmZpY2Uuc3ZjXEVycm9yUmVwb3J0?=
Content-Length: 0
Cache-Control: private
Date: Thu, 27 Apr 2017 03:19:29 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
}
IsFromCache: false
IsMutuallyAuthenticated: false
ResponseUri: {http://localhost:54945/Take2ToOffice.svc/ErrorReport}
SupportsHeaders: true
But there is no actual response at all (length = 0). If I put a breakpoint in the service, (and start both the test form, and the service - separate projects in the same solution), the breakpoint is never hit.
Logically it looks like the service isn't running, or for some reason can't be found - but the listing and success page are readily seen in a browser, and at the address (localhost:54945) shown in the program.
Can anyone explain what's going on, or maybe what's going wrong? Please help, I'm totally stumped.
The web.config is as follows:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
...
</connectionStrings>
<appSettings>
...
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime/>
</system.web>
<system.serviceModel>
<services>
<service name="Take2OfficeCommunications.Take2ToOffice" behaviorConfiguration="serviceBehavior">
<endpoint address="rest"
binding="webHttpBinding"
bindingConfiguration="WebBinding"
behaviorConfiguration="web"
name="restEndpoint"
contract="Take2OfficeCommunications.ITake2ToOffice"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="WebBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="Transport" />
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Thanks for looking, and for any comments you can make.

How to invoke web service in client which has CustomBinding endpoints?

I have WCF web service with custombinding as endpoint. I would like to invoke this web service (hosted on IIS) from my client application.
The service contract looks as below:
[ServiceContract(Namespace = "http://schemas.microsoft.com/windows/management/2012/01/enrollment")]
[XmlSerializerFormat]
public interface IDiscoveryService
{
[OperationContract(Name = "Get")]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat=WebMessageFormat.Xml, ResponseFormat=WebMessageFormat.Xml)]
string DiscoveryGet();
}
The Web.COnfig file contents looks like:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
<services>
<service name="DiscoveryWebService.DiscoveryService">
<endpoint address="" binding="customBinding" bindingConfiguration="NewBinding0"
contract="DiscoveryWebService.IDiscoveryService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value 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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
The client application codes looks like:
string uri = " http://localhost/EnrollmentServer/Discovery.svc";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.ContentType = "unknown";
req.Method = "GET";
WebResponse response = req.GetResponse();
StreamReader loResponseStream = new StreamReader(response.GetResponseStream(), false);
string responseString = loResponseStream.ReadToEnd();
I am getting HTML content of WSDL file instead of the string returned by Get method. I am not getting whether I am doing it in the right way or not?
I would appreciate the help in this regard.
The [WebGet] (and [WebInvoke]) attribute is only honored for an endpoint which uses the webMessageEncoding binding element; with a HTTP transport with the manualAddressing property set to true, and also the <webHttp/> endpoint behavior - which your service doesn't have. If you make the changes listed below, it should work:
Service contract:
[ServiceContract(Namespace = "http://schemas.microsoft.com/windows/management/2012/01/enrollment")]
[XmlSerializerFormat]
public interface IDiscoveryService
{
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
string DiscoveryGet();
}
Web.config:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="NewBinding0">
<webMessageEncoding />
<httpTransport manualAddressing="true" />
</binding>
</customBinding>
</bindings>
<services>
<service name="DiscoveryWebService.DiscoveryService">
<endpoint address="" binding="customBinding" bindingConfiguration="NewBinding0"
contract="DiscoveryWebService.IDiscoveryService" behaviorConfiguration="Web" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="Web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client code:
string uri = "http://localhost/EnrollmentServer/Discovery.svc/DiscoveryGet";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "GET";
WebResponse response = req.GetResponse();
StreamReader loResponseStream = new StreamReader(response.GetResponseStream(), false);
string responseString = loResponseStream.ReadToEnd();

WCF authentication is not working

I am using Message Security for WCF authentication. And my clientCredentialType="UserName".
Even if I am not providing valid username and password while accessing a service, it is working fine.
It should do authentication, If credentials are correct then only it should allow to access.`enter code here
The code is as follows:
WCF service behaviour section:
<behaviors>
<serviceBehaviors>
<behavior name="AuthenticationBehaviour">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfServiceAuthentication.Authenticator, WcfServiceAuthentication"/>
</serviceCredentials>
<!-- 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>
WCF Service Binding section in Web.config
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
My authentication class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IdentityModel.Selectors;
using System.ServiceModel;
using log4net;
using System.Reflection;
namespace WcfServiceAuthentication
{
public class Authenticator : UserNamePasswordValidator
{
private static ILog _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public override void Validate(string userName, string password)
{
_logger.Info("Validate called with username:" + userName + " and password:" + password);
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == "Admin" && password == "Admin123"))
{
// This throws an informative fault to the client.
throw new FaultException("Unknown Username or Incorrect Password");
}
_logger.Info("End called");
}
}
}
My Authentication service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class AuthenticationService : IAuthenticationService
{
public int add(int num1, int num2)
{
return (num1 + num2);
}
}
}
And Client application:
AuthenticationServiceClient proxy = new AuthenticationServiceClient();
//proxy.ClientCredentials.UserName.UserName = "Admin";
//proxy.ClientCredentials.UserName.Password = "Admin123";
int addition= proxy.add(10, 10);
return View();
Here even though I am not providing credentials, Add method is working fine. It should ask for Authentication.
Modify the web config by adding the below tags to enable authentication service.
<system.web.extensions> <scripting>
<webServices>
<authenticationService enabled="true"
requireSSL = "true"/>
</webServices> </scripting> </system.web.extensions>
It should be added to the web config file. The sample is as here
<system.web.extensions>
<scripting>
<webServices>
<authenticationService enabled="true"
requireSSL = "true"/>
</webServices>
</scripting>
</system.web.extensions>
<system.serviceModel>
<services>
<service name="System.Web.ApplicationServices.AuthenticationService"
behaviorConfiguration="AuthenticationServiceTypeBehaviors">
<endpoint contract=
"System.Web.ApplicationServices.AuthenticationService"
binding="basicHttpBinding"
bindingConfiguration="userHttps"
bindingNamespace="http://asp.net/ApplicationServices/v200"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="userHttps">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="AuthenticationServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

FileTransfer to WCF Service receiving 405

I'm working on a mobile app using PhoneGap, and one of the features involves uploading an image to a web service for processing. I've written a WCF service that's hosted in IIS to accept the image, with a contract that looks like the following:
[ServiceContract]
public interface IImages
{
[OperationContract(Name="UploadImage")]
[WebInvoke(UriTemplate = "?file_key={fileKey}", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare)]
ImageResource UploadImage(string fileKey, Stream imageStream);
}
The configuration section in my web.config looks like:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<serviceActivations>
<add service="Services.Images" relativeAddress="images.svc" />
</serviceActivations>
</serviceHostingEnvironment>
<services>
<service behaviorConfiguration="DefaultServiceBehavior" name="Services.Images">
<endpoint behaviorConfiguration="DefaultEndpointBehavior" binding="webHttpBinding" bindingConfiguration="PublicStreamBinding" contract="Services.Contracts.IImages" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="PublicStreamBinding"
maxReceivedMessageSize="2000000000" transferMode="Streamed">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="DefaultEndpointBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="DefaultServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="30" maxConcurrentInstances="30" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
When I attempt to upload a file to the endpoint, using PhoneGap's FileTransfer class, the response returned from the service is a 405 Method Not Allowed. What am I doing wrong here?
UPDATE: The function in my mobile app that's uploading the file is below. This code previous worked fine when pointed to an older ASMX service.
ns.UploadImage = function(){
//alert(ns.Dictionary['LocalImagePath']);
var uri = ns.Dictionary['LocalImagePath'];
try {
var options = new FileUploadOptions();
options.fileKey = uri.substr(uri.lastIndexOf('/')+1) + ".jpeg";
options.fileName = uri.substr(uri.lastIndexOf('/')+1) + ".jpeg";
options.mimeType = "image/jpeg";
var ft = new FileTransfer();
ft.upload(uri, GetServerUrl()+"images.svc?file_key="+options.fileKey, ns.UploadImageSuccess, ns.UploadImageError, options);
} catch (e) {
ns.UploadImageError(e);
}
};
Ok so I think I figured this out. Apparently, when the method is hosted at the root like this, if you don't follow the name of the service in the uri with '/', the request won't get routed correctly. So, in the function that uploads the file, I changed the ft.upload line to the following:
ft.upload(uri, GetServerUrl()+"images.svc/?file_key="+options.fileKey, ns.UploadImageSuccess, ns.UploadImageError, options);
Which worked.

In WCF, for a webHttpBinding, how do I specify credentials in the client side web.config when the server is using basic authentication?

I have two WCF RESTful services - the "general" service is public and has no security; the "admin" service I intend to use basic authentication over SSL. This is my server side web.config:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="general" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="admin" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyNamespace.AppServices.GeneralService">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.Contracts.IGeneralService" behaviorConfiguration="web" bindingConfiguration="general" />
</service>
<service name="MyNamespace.AppServices.AdminService">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.Contracts.IAdminService" behaviorConfiguration="web" bindingConfiguration="admin" />
</service>
</services>
</system.serviceModel>
On the client side, I currently have code that looks like this:
private static IGeneralService GetGeneralChannel()
{
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.None;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.MaxReceivedMessageSize = Int32.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
WebChannelFactory<IGeneralService> cf = new WebChannelFactory<IGeneralService>(binding, new Uri("http://localhost:1066/GeneralService"));
IGeneralService channel = cf.CreateChannel();
return channel;
}
private static IAdminService GetAdminChannel()
{
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.MaxReceivedMessageSize = Int32.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
WebChannelFactory<IAdminService> cf = new WebChannelFactory<IAdminService>(binding, new Uri("http://localhost:1066/AdminService"));
cf.Credentials.UserName.UserName = "myUserName";
cf.Credentials.UserName.Password = "myPassword";
IAdminService channel = cf.CreateChannel();
return channel;
}
The question is, since I obviously do not want to hard-code all of this configuration information, how do I need to provide it in the web.config on the client? It is pretty clear to me that the binding element needs to look pretty much the same on the client as it does on the server. However, where do I indicate the credentials that are assigned to the WebChannelFactory?
Any help and/or insight will be appreciated.
Thanks,
Steve
You cannot put those credentials (username and password) into web.config and have WCF read them from there. This is one of the very few features in WCF which cannot be done in config - you have to set those credentials in your code.
Of course, in your code, you can read them from e.g. a database table, or a config entry somewhere - but you have to do that yourself. WCF can't be configured to automagically read those settings from somewhere.