In my web project I have a TestStreamingService.svc file containing a REST service.
The service contract :
[ServiceContract(Namespace = "")]
public interface ITestStreamingService
{
[OperationContract]
[WebGet(UriTemplate = "Download?file={file}&size={size}")] //file irrelevant, size = returned size of the download
Stream Download(string file, long size);
[OperationContract]
[WebInvoke(UriTemplate= "Upload?file={file}&size={size}", Method = "POST")]
void Upload(string file, long size, Stream fileContent);
[OperationContract(AsyncPattern=true)]
[WebInvoke(UriTemplate = "BeginAsyncUpload?file={file}", Method = "POST")]
IAsyncResult BeginAsyncUpload(string file, Stream data, AsyncCallback callback, object asyncState);
void EndAsyncUpload(IAsyncResult ar);
}
The service implementation (the *.svc file)
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using ICode.SHF.Tests;
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class TestStreamingService : ITestStreamingService
{
public Stream Download(string file, long size)
{
return new SHFTestStream(size);
}
public void Upload(string file, long size, Stream fileContent)
{
FileInfo f = new FileInfo(String.Format(#"C:\{0}", file));
using (FileStream fs = f.Create())
{
CopyStream(fileContent, fs);
fs.Flush();
fs.Close();
}
}
public IAsyncResult BeginAsyncUpload(string file, Stream data, AsyncCallback callback, object asyncState)
{
return new CompletedAsyncResult<Stream>(data, file);
}
public void EndAsyncUpload(IAsyncResult ar)
{
Stream data = ((CompletedAsyncResult<Stream>)ar).Data;
string file = ((CompletedAsyncResult<Stream>)ar).File;
StreamToFile(data, file);
}
private void StreamToFile(Stream data, string file)
{
string subDir = Guid.NewGuid().ToString("N");
string uploadDir = Path.Combine(Path.GetDirectoryName(typeof(TestStreamingService).Assembly.Location), subDir);
Directory.CreateDirectory(uploadDir);
byte[] buff = new byte[0x10000];
using (FileStream fs = new FileStream(Path.Combine(uploadDir, file), FileMode.Create))
{
int bytesRead = data.Read(buff, 0, buff.Length);
while (bytesRead > 0)
{
fs.Write(buff, 0, bytesRead);
bytesRead = data.Read(buff, 0, buff.Length);
}
}
}
}
public class CompletedAsyncResult : IAsyncResult
{
T data;
string file;
public CompletedAsyncResult(T data, string file)
{ this.data = data; this.file = file; }
public T Data
{ get { return data; } }
public string File
{ get { return file; } }
#region IAsyncResult Members
public object AsyncState
{
get { return (object)data; }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get { throw new NotImplementedException(); }
}
public bool CompletedSynchronously
{
get { return true; }
}
public bool IsCompleted
{
get { return true; }
}
#endregion
}
My Web.Config
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="ICode.SHF.SL.Tests.Web.TestStreamingService.customBinding0"/>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
/>
<services>
<service name="ICode.SHF.SL.Tests.Web.TestStreamingService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:40000/Streaming"/>
</baseAddresses>
</host>
<endpoint name="TestStreamingEndpoint" address="RESTService" binding="webHttpBinding" bindingConfiguration="ICode.SHF.SL.Tests.Web.TestStreamingService.customBinding0"
contract="ICode.SHF.SL.Tests.Web.ITestStreamingService" behaviorConfiguration="REST"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
I'm trying to consume the service from silverlight (the web project contains a clientaccesspolicy.xml) via a WebClient however I seem to fail, Fiddler doesn't show any calls being made.
(using WebClient.OpenWriteAsync (for upload) & OpenReadAsync (for download))
The uri used for the Client is : "http://localhost:40000/Streaming/Service/Download?file=xxx&size=65536"
When I use the following uri in IE : "http://localhost:40000/TestStreamingService.svc/Download?file=xxx&size=65536" a download operation begins and the downloaded file matches the size passed.
I'm not having success with the IE uri in the WebClient though.
Could anyone please explain to me what am I doing wrong? It seems I've missed something fundamental...
Do your site require authentication? As for fiddler, try connecting your webclient to:
http://localhost.:40000/Streaming/Service/Download?file=xxx&size=65536
(note the extra dot after localhost)
It would appear that I've managed to solve my problem regarding the Downloading capability from Silverlight via. WebClient.
Here's what I did.
Moved the service contract and implementation to a separate project MyWCFLibrary (WCF Service Library)
Added a reference of the said library to the ASP.NET website hosting the project
Added a text file "Service.svc" and edited it :
<%# ServiceHost Language="C#" Debug="true" Service="MyWCFLibrary.TestStreamingService" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
Modified the WebClient operation's uri to match the *.svc file
Seems that it worked.
I'm still attemptring to figure one thing out, so comments are welcome :
I can perform an operation on the service via the Webclient like this :
WebClient wc = new WebClient();
string uri = String.Format("http://localhost.:40000/Service.svc/Download?file=xxx&size={0}", size);
wc.OpenReadAsync(new Uri(uri));
but not like this :
string uri = String.Format("http://localhost.:40000/Services/StreamingService/Download?file=xxx&size={0}", size);
wc.OpenReadAsync(new Uri(uri));
Where : localhost:40000/Services is the base address of the service and StreamingService is the address of the endpoint (latest changes in my WebConfig)
Can anyone explain why? or am I stuck with using the 1st uri by default?
Related
I have to call a WCF service. The WCF service is on and I can edit its configuration.
I want to create a client that calls the service. I cannot add the service reference to my client, so I am trying to call it with a HttpClient.
The client side code:
using (var client = new HttpClient())
{
//soapString is my input class serialized
var content = new StringContent(soapString, Encoding.UTF8, "text/xml");
using (var postResponse = client.PostAsync("http://localhost:52937/Attempts.svc/", content).Result)
{
string postResult = postResponse.Content.ReadAsStringAsync().Result;
}
}
The server side code:
[ServiceContract]
public interface IAttempts
{
[OperationContract]
void ReceiveAttemptResult(ReceiveAttemptResultInput result);
}
public class Attempts : IAttempts
{
string _backendUrl;
public void ReceiveAttemptResult(ReceiveAttemptResultInput result)
{
//...
}
}
And in the end the web.config server side:
<system.serviceModel>
<services>
<service name="it.MC.Listeners.Attempts">
<endpoint address="" contract="it.MC.Listeners.IAttempts" binding="basicHttpBinding"/>
<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
When I call the service, I just obtain an empty string and I cannot stop in debug inside the service... What's wrong?
Thank you
Just in case this bedevils anyone else. Thank you #Disappointed for your missing piece of the puzzle, it prompted me to run the thing in WCF Test Client with Fiddler open to see what I was missing:
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("SOAPAction", "http://tempuri.org/IMyService/Mymethod_Async");
string soapEnvelope = "<s:Envelope xmlns:s= \"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><Mymethod_Async xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
var content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml");
HttpResponseMessage hrm = httpClient.PostAsync("http://MyService.MyDomain.com/MyService.svc", content).Result;
I have very little experience in WCF and I want to upload file on server from client machine via WCF service (using streaming). I read few topics and wrote a simple example by myself, but unfortunately it's not working
This is an interface code:
[ServiceContract]
public interface IService1
{
[OperationContract]
string UpStream(FileStream inStream);
}
This is implementation:
public string UpStream(FileStream inStream)
{
using(StreamReader sr = new StreamReader(inStream))
{
var recievedText = sr.ReadToEnd();
if (recievedText != "")
{
return recievedText;
}
else
{
return "nothing";
}
}
}
This is a client code:
private void button3_Click(object sender, EventArgs e)
{
service2.Service1Client sc = new service2.Service1Client();
OpenFileDialog opf = new OpenFileDialog();
opf.ShowDialog();
if (opf.FileName != "")
{
using (FileStream inStream = File.Open(opf.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
MessageBox.Show(sc.UpStream(inStream));
}
}
}
I think that problem must be somewhere in config file or in Stream. When I start client program and invoke UpStream method, WCF-service is recieving an empty stream
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services />
<bindings>
<basicHttpBinding>
<binding name="NewBinding0" maxBufferPoolSize="52428800" maxBufferSize="65536000"
maxReceivedMessageSize="6553600000" transferMode="Streamed"
useDefaultWebProxy="true" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
If anyone can help me with solving my problem, I'll be very grateful
Streaming is very useful but a little tricky to get your head around
this MSDN article provides lots of details https://msdn.microsoft.com/en-us/library/ms733742%28v=vs.110%29.aspx
but doesn't make some of the details very clear
firstly you need to pass messages rather than parameters
this would look something like
[MessageContract]
public class DataTransfer
{
[MessageHeader(MustUnderstand = true)]
public DataContract.HandShake Handshake { get; set; }
[MessageBodyMember(Order = 1)]
public Stream Data { get; set; }
//notice that it is using the default stream not a file stream, this is because the filestream you pass in has to be changed to a network stream to be sent via WCF
}
where the HandShake class provides the parameters you need to include along with your stream
public SaveResponse SaveData(DataTransfer request)
{
using (var stream = new System.IO.MemoryStream())
{
request.Data.CopyTo(stream);
stream.Position = 0;
//this is because you have less control of a stream over a network than one held locally, so by copying from the network to a local stream you then have more control
next is configuration: you have to configure for streaming on both the server and client
which requires something like this
<bindings>
<basicHttpBinding>
<binding name="ServiceBinding" transferMode="Streamed" messageEncoding="Mtom" maxReceivedMessageSize="67108864" maxBufferSize="65536" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
</binding>
</basicHttpBinding>
</bindings>
I need to upload a big file to Azure storage. As a first step, I am trying to upload the file to web service folder via wcf service. I followed the steps in this link Streaming files over WCF. My service code:
namespace MilkboxGames.Services
{
[ServiceContract]
public interface IFileUploadService
{
[OperationContract]
UploadResponse Upload(UploadRequest request);
}
[MessageContract]
public class UploadRequest
{
[MessageHeader(MustUnderstand = true)]
public string BlobUrl { get; set; }
[MessageBodyMember(Order = 1)]
public Stream data { get; set; }
}
[MessageContract]
public class UploadResponse
{
[MessageBodyMember(Order = 1)]
public bool UploadSucceeded { get; set; }
}
}
And
namespace MilkboxGames.Services
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class FileUploadService : IFileUploadService
{
#region IFileUploadService Members
public UploadResponse Upload(UploadRequest request)
{
try
{
string uploadDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
string path = Path.Combine(uploadDirectory, "zacharyxu1234567890.txt");
if (File.Exists(path))
{
File.Delete(path);
}
const int bufferSize = 2048;
byte[] buffer = new byte[bufferSize];
using (FileStream outputStream = new FileStream(path, FileMode.Create, FileAccess.Write))
{
int bytesRead = request.data.Read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
outputStream.Write(buffer, 0, bytesRead);
bytesRead = request.data.Read(buffer, 0, bufferSize);
}
outputStream.Close();
}
return new UploadResponse
{
UploadSucceeded = true
};
}
catch (Exception ex)
{
return new UploadResponse
{
UploadSucceeded = false
};
}
}
#endregion
}
}
Web.config:
<?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" executionTimeout="600"
maxRequestLength="2097152" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="FileUploadServiceBinding" messageEncoding="Mtom" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" receiveTimeout="00:15:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00" transferMode="Streamed">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MilkboxGames.Services.FileUploadService" behaviorConfiguration="FileUploadServiceBehavior">
<endpoint address=""
binding="basicHttpBinding" contract="MilkboxGames.Services.IFileUploadService" bindingConfiguration="FileUploadServiceBinding">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="FileUploadServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
</configuration>
To consume this service, I created a console application and added the wcf service to Service References. I noticed that the service method becomes 'public bool Upload(string BlobUrl, System.IO.Stream data)' instead of 'public UploadResponse Upload(UploadRequest request)'. Can somebody explain to me why?
Client code:
string blobUrl = "assassinscreedrevelationsandroid/GT-I9100G/assassinscreedrevelationsandroid.apk";
string fileName = "C:\\ws_new\\XuConsoleApplication\\XuConsoleApplication\\bin\\Debug\\motutcimac.myar";
bool bUploadBlobResult;
byte[] buffer = File.ReadAllBytes(fileName);
Console.WriteLine("Size = " + buffer.Length);
Stream fileStream = System.IO.File.OpenRead(fileName);
FileUploadServiceClient objFileUploadServiceClient = new FileUploadServiceClient();
bUploadBlobResult = objFileUploadServiceClient.Upload(blobUrl, fileStream);
I managed to upload a file of 123.8MB. When I try to upload a file of 354.6MB, I got the following exception:
Unhandled Exception: System.InsufficientMemoryException: Failed to allocate
a managed memory buffer of 371848965 bytes. The amount of available memory
may be low. ---> System.OutOfMemoryException: Exception of type
'System.OutOfMemoryException' was thrown.
at System.Runtime.Fx.AllocateByteArray(Int32 size)
--- End of inner exception stack trace ---
I am unable to figure out why this happened. Any help or advice are appreciated.
Unhandled Exception: System.InsufficientMemoryException: Failed to
allocate a managed memory buffer of 371848965 bytes. The amount of
available memory may be low.
above message is indicating your app is using up all the memory that allowed, to increase the limit i think you will need a larger value on attribute "maxReceivedMessageSize"
also from another thread (Failed to allocate a managed memory buffer of 134217728 bytes. The amount of available memory may be low), it recommend to use stream transfer mode for large file upload.
Use Stream property in message contract of WCF operation to transfer
large objects.
[MessageContract]
public class DocumentDescription
{
[MessageBodyMember(Namespace = "http://example.com/App")]
public Stream Stream { get; set; }
}
Configure your binding this way
<binding name="Binding_DocumentService" receiveTimeout="03:00:00"
sendTimeout="02:00:00" transferMode="Streamed" maxReceivedMessageSize="2000000">
<security mode="Transport" />
</binding>
I have construct a simple secured wcf with wsHttpBinding in .Net C# (framework 4.5) and consume it from .Net C# (also) client and every thing work fine. But when I try to consume It from php (5.5) client by calling a method from the wcs service, the client not work and it has entered in an infinite loop and not showing any error message, just looping.
a. The following is my wcf ServiceContract and OperationContract's:
namespace CenteralServices
{
[ServiceContract]
public interface IAdminServices
{
[OperationContract]
int Add(int x, int y);
}
}
b. The following is the configueration file Web.config for the wcf:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<services>
<service name= "CentralTicketServicesSystem.AdminSystem"
behaviorConfiguration="customBehaviour">
<endpoint address="AdminServices"
binding="wsHttpBinding"
contract="CentralTicketServicesSystem.IAdminServices"
bindingConfiguration="ServiceBinding"
behaviorConfiguration="MyEndPointBehavior">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/AdminServicesSystem" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="ServiceBinding"
openTimeout="00:10:00"
closeTimeout="00:10:00"
receiveTimeout="00:10:00"
sendTimeout="00:10:00">
<security mode="Message" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="MyEndPointBehavior">
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="customBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="CentralServicesHost.AuthorizationPolicy, CentralServicesHost" />
</authorizationPolicies>
</serviceAuthorization>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CentralServicesHost.UserAuthentication, CentralServicesHost"/>
<serviceCertificate findValue="15 63 10 5e b6 4b 4d 85 4b 2e 4d 5b ec 85 02 ec"
storeLocation="LocalMachine"
x509FindType="FindBySerialNumber"
storeName="My"/>
</serviceCredentials>
</behavior>
<behavior name="mexBehaviour" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
c. The following is UserAuthentication class:
namespace CentralServicesHost
{
public class UserAuthentication : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password");
if (userName != "test" && password != "test")
throw new FaultException("Unknown Username or Incorrect Password.");
}
}
}
d. The following is AuthorizationPolicy class:
namespace CentralServicesHost
{
public class AuthorizationPolicy : IAuthorizationPolicy
{
Guid _id = Guid.NewGuid();
// this method gets called after the authentication stage
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
// get the authenticated client identity
IIdentity client = GetClientIdentity(evaluationContext);
// set the custom principal
evaluationContext.Properties["Principal"] = new CustomPrincipal(client);
return true;
}
private IIdentity GetClientIdentity(EvaluationContext ec)
{
object obj;
if (!ec.Properties.TryGetValue("Identities", out obj))
throw new Exception("No Identity found");
IList<IIdentity> identities = obj as IList<IIdentity>;
if (identities == null || identities.Count <= 0)
throw new Exception("No Identity found");
return identities[0];
}
public System.IdentityModel.Claims.ClaimSet Issuer
{
get { return ClaimSet.System; }
}
public string Id
{
get { return _id.ToString(); }
}
}
}
e. The following is CustomPrincipal class:
namespace CentralServicesHost
{
class CustomPrincipal : IPrincipal
{
IIdentity _identity;
string[] _roles;
public CustomPrincipal(IIdentity identity)
{
_identity = identity;
}
// helper method for easy access (without casting)
public static CustomPrincipal Current
{
get
{
return Thread.CurrentPrincipal as CustomPrincipal;
}
}
public IIdentity Identity
{
get { return _identity; }
}
// return all roles
public string[] Roles
{
get
{
EnsureRoles();
return _roles;
}
}
// IPrincipal role check
public bool IsInRole(string role)
{
EnsureRoles();
return (_roles != null) ? _roles.Contains(role) : false;
}
// read Role of user from database
protected virtual void EnsureRoles()
{
using (var s = new SupportedMaterialsSystemEntities())
{
_roles = new string[1] { "admin" };
}
}
}
}
f. The following is my php client code:
<?php
$options = array('soap_version' => SOAP_1_2,
'login' => 'test',
'password' => 'test');
$wsdl = "http://localhost:8080/AdminServicesSystem";
$client = new SoapClient($wsdl, $options);
$obj = new stdClass;
$obj->x = 3;
$obj->y = 3;
$retval = $client->Add($obj);//here the browser loops for infinite without any response.
//var_dump($exc);//THIS POINT NOT REACHED
//die();
$result = $retval->AddResult;
echo $result;
NOTES:
1. My OS is Win. 8.1, and I'm using visual studio 2013 (as adminstrator) and php Wamp Server.
2. I tried both, hosting the wcf service in IIS 6.2 and console application but non of them changes my php client looping.
3. I have Created the self-signed certificate usin the IIS manager that stores it in my local machine.
4. When I change the soap_version in the php code from SOAP_1_2 to SOAP_1_1 I had Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'..
Last Note:
My .Net C# Client code is the following:
using (var svcProxy = new AdminServiceProxy.AdminServicesSystemClient())
{
svcProxy.ClientCredentials.UserName.UserName = "test";
svcProxy.ClientCredentials.UserName.Password = "test";
Console.WriteLine(svcProxy.Add(1, 1));//the service works fine and print 2
}
}
So agin, What is the right way to call a secured wcf (with wsHttpBinding) service from php.
I believe you need a default WSDL metadata published to use PHP soap client (see abilities here http://php.net/manual/en/intro.soap.php).
Try to add endpoint with basicHttpBinding binding, which can provide WSDL for your client and then use this endpoint.
On the address http://localhost:8080/AdminServicesSystem you have endpoint with mexHttpBinding, which provides metadata int other format (http://www.w3.org/TR/2009/WD-ws-metadata-exchange-20090317/).
Try to see here form more details: https://abhishekdv.wordpress.com/2013/05/24/mexhttpbinding-vs-wsdl/
I am having trouble developing and testing a POST web service which both receives and returns JSON.
I am testing it (or trying/wanting to test it) by calling it from a form in a test project within the same
solution as the web service. However it seems that no matter what I do, I'm getting either a "Bad Request", or
a "Not Found" error when invoking the service.
There are oodles of posts on the web in relation to these things, and WCF in general, with examples etc, but I
cannot seem to solve the problem and it's quite disheartening :-((.
I am using VS 2010 on (don't laugh) win XP. However I don't see why an outdated OS should matter.
The single method's signature is
public Stream ReceiveCardStatusInfo(Stream request)
I have generated a proxy via svcutil, but I'm not using it. I have tried referencing the webservice project as
both an ordinary and a service reference (currently a service reference). The properties of the projects are
pretty much the defaults, but in trying to resolve the issues, the web page of the WS project currently shows
"Use Visual Studio Development Server" with "Specific Port" selected, port number 1318. (Virtual Path is the
default "/").
As I'm not really sure exactly what the problem is, I am providing all my code and config files;
the Form's logic first (used to invoke the service) and the app.config for that project, with the service
components following:
Form1:
public Form1() {
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e) {
var request = (HttpWebRequest)WebRequest.Create("http://localhost:1318/ReceiveData.svc/ReceiveCardStatusInfo"); // /ReceiveCardStatusInfo
request.ContentType = "text/json";
request.Method = "POST";
string json = new JavaScriptSerializer().Serialize(new {
AuthenticationToken = "...",
Campus = "Te Awamutu",
StudentID = "200122327",
EnrolmentEndDate = "11/06/2015",
CardStatus = "Suspended",
SuspendedDate = "18/08/2014",
OrderedDate = "20/09/2014",
ReprintDate = "07/10/2014"
});
using (var sW = new StreamWriter(request.GetRequestStream())) {
sW.Write(json);
sW.Flush();
sW.Close();
}
var response = (HttpWebResponse)request.GetResponse();
string result;
using (var streamReader = new StreamReader(response.GetResponseStream())) {
result = streamReader.ReadToEnd();
}
MessageBox.Show(result);
}
app.config (I don't really understand exactly what needs to be in this file, but I've had trouble finding a
clear answer to this, so it contains what it does):
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="StudentCardStatusData.ReceiveData" behaviorConfiguration="serviceBehaviour">
<endpoint address="" binding="webHttpBinding" contract="StudentCardStatusData.IReceiveData" behaviorConfiguration="web"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="webHttpBinding_IReceiveData" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</webHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1318/ReceiveData.svc" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IReceiveData" contract="IReceiveData" name="webHttpBinding_IReceiveData"/>
<!-- endpoint address="..." binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IReceiveData" contract="IReceiveData"
name="BasicHttpBinding_IReceiveData" / -->
</client>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
</configuration>
Web Service:
IReceiveData:
namespace StudentCardStatusData {
[DataContract]
public class StatusInfo {
private string _Authent;
private string _Campus;
private string _StudentID;
private string _EnrolmentEndDate;
private string _CardStatus;
private string _SuspendedDate;
private string _OrderedDate;
private string _ReprintDate;
[DataMember(Name="AuthenticationToken")]
public string AuthenticationToken {
get { return _Authent; }
set { _Authent = value; }
}
[DataMember(Name="Campus")]
public String Campus {
get { return _Campus; }
set { _Campus = value; }
}
[DataMember(Name="StudentID")]
public String StudentID {
get { return _StudentID; }
set { _StudentID = value; }
}
[DataMember(Name="EnrolmentEndDate")]
public String EnrolmentEndDate {
get { return _EnrolmentEndDate; }
set { _EnrolmentEndDate = value; }
}
[DataMember(Name="CardStatus")]
public String CardStatus {
get { return _CardStatus; }
set { _CardStatus = value; }
}
[DataMember(Name="SuspendedDate")]
public String SuspendedDate {
get { return _SuspendedDate; }
set { _SuspendedDate = value; }
}
[DataMember(Name = "OrderedDate")]
public String OrderedDate {
get { return _OrderedDate; }
set { _OrderedDate = value; }
}
[DataMember(Name = "ReprintDate")]
public String ReprintDate {
get { return _ReprintDate; }
set { _ReprintDate = value; }
}
}
[ServiceContract]
public interface IReceiveData {
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "ReceiveCardStatusInfo")]
Stream ReceiveCardStatusInfo(Stream request);
}
}
ReceiveData.svc:
namespace StudentCardStatusData {
public class ReceiveData : IReceiveData {
public Stream ReceiveCardStatusInfo(Stream request) {
Stream res = new MemoryStream();
StreamWriter sw = new StreamWriter(res);
try {
ConnectionStringSettings _DefaultSetting = ConfigurationManager.ConnectionStrings["Take2"];
SqlConnection cnn = new SqlConnection(_DefaultSetting.ConnectionString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
//
if (request != null) {
StreamReader sr = new StreamReader(request);
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<StatusInfo> allitems = serializer.Deserialize<List<StatusInfo>>(sr.ReadToEnd());
bool isFirst = true;
foreach (var item in allitems) {
if (isFirst) {
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "SELECT Cast(AuthenticationKey as varchar(50)) FROM IDCardAuthentication";
cmd.Connection.Open();
object o = cmd.ExecuteScalar();
cmd.Connection.Close();
if ((string)o != item.AuthenticationToken.ToUpper()) {
sw.Write("[{\"Result\":\"Undefined Failure\"}]");
return res;
}
isFirst = false;
}
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "dbo.spSaveStudentCardStatus";
cmd.Parameters.Add(new SqlParameter("#Campus", item.Campus));
cmd.Parameters.Add(new SqlParameter("#PerID", item.StudentID));
cmd.Parameters.Add(new SqlParameter("#EndDate", item.EnrolmentEndDate));
cmd.Parameters.Add(new SqlParameter("#Status", item.CardStatus));
cmd.Parameters.Add(new SqlParameter("#Upload", item.SuspendedDate));
cmd.Parameters.Add(new SqlParameter("#Ordered", item.OrderedDate));
cmd.Parameters.Add(new SqlParameter("#Reprint", item.ReprintDate));
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Connection.Close();
}
}
sw.Write("[{\"Result\":\"Success\"}]");
return res;
}
catch (Exception ex) {
sw.Write("[{\"Result\":\"" + ex.Message + "\"}]");
return res;
}
}
}
}
Web.Config:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="Take2"
connectionString="..."
providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="StudentCardStatusData.ReceiveData" behaviorConfiguration="StudentCardStatusData.ReceiveDataBehavior">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" contract="StudentCardStatusData.IReceiveData" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="https://localhost:1318/ReceiveData.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="StudentCardStatusData.ReceiveDataBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Very first requirement to consume any service is that “Service is Up and Running on Service” here in local ISS in your case.
The reason for getting "Bad Request", or a "Not Found" error when invoking the service is possibility that it is not running on server (localhost).
Are you able to view service page from browser by HTTP request of page "ReceiveData.svc" on your endpoints.
If not then you have to make sure that your service is all ready running before you start consuming it.
As you said that you are running it from same solutions, I am sure you are stating multiple application at the same time. I mean that the Service Application and Consuming Application.
If not you can run multiple start up application from same solution by settings in
Go to Solution properties -> Common properties -> Start up Project and select Multiple start up projects.
So now when you run the solution your both application will start and you should be able to use service.
EDIT
I created test application with all your given code..!!
And it gave me same error..!!!!
So I changed;
request.ContentType = "'text/json; charset=utf-8'";
and it worked..!!! ;)
So please try that.
Hope it helps..!!