upload image using PhoneGap to .NET WCF Rest Service - wcf

I am facing problem upload file from camera and gallery.
When selecting few images from gallery I am able to successfully upload the image to WCF service. Thus WCF service is working fine and so is the code to upload file and also same code works with emulated web camera also.
However when selecting a few images from gallery I am getting *error code *
java.io.FileNotFoundException: http://www.foobar.com/sasas
JavaScript Code
function selectImageFromCamera(){
var popover = new CameraPopoverOptions(300,300,100,100,Camera.PopoverArrowDirection.ARROW_ANY);
var options = { quality: 49, destinationType: Camera.DestinationType.FILE_URI,sourceType: Camera.PictureSourceType.CAMERA, popoverOptions : popover};
navigator.camera.getPicture(this.uploadPhoto, this.onFail, options);
}
function selectImageFromGallery(){
var popover = new CameraPopoverOptions(300,300,100,100,Camera.PopoverArrowDirection.ARROW_ANY);
var options = { quality: 49, destinationType: Camera.DestinationType.FILE_URI,sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY, popoverOptions : popover};
navigator.camera.getPicture(this.uploadPhoto, this.onFail, options);
}
function uploadPhoto(imageURI) {
var serverUrl = "http://www.foobar.com/safafa";
var image = document.getElementById("imgUpload");
image.style.display = "block";
image.src = imageURI;
var fileUploadOptions = new FileUploadOptions();
fileUploadOptions.fileKey="file";
fileUploadOptions.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
fileUploadOptions.mimeType="image/png";
fileUploadOptions.chunkedMode=true;
var ft = new FileTransfer();
ft.upload(imageURI, serverUrl, this.win, this.fail, fileUploadOptions);
}
Please help me to identify What I am doing wrong.

Your PhoneGap code seems to be all right but just check your WCF Service web.config File.
You'll want something like this to increase the file size.
<bindings>
<basicHttpBinding>
<binding name="basicHttp" allowCookies="true"
maxReceivedMessageSize="10000000"
maxBufferSize="10000000"
maxBufferPoolSize="10000000">
<readerQuotas maxDepth="32"
maxArrayLength="100000000"
maxStringContentLength="100000000"/>
</binding>
</basicHttpBinding>
</bindings>
where 100000000 is your file size.

This worked for me.
The issue was with the WCF service. Its accepted file less than 65 KB, which is max request size by default after increasing maxReceivedMessageSizevalue problem was solved.
<standardEndpoint name=""
helpEnabled="true"
automaticFormatSelectionEnabled="true"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
</standardEndpoint>

Related

How to change default message size using ClearUserNameBinding?

We are using ClearUserNameBindig in our WCF service.
When we tried to return a message with more than 3k records, we received this error:
The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
We tried to modify web.config like that:
<bindings>
<clearUsernameBinding>
<binding name="myClearUsernameBinding"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000" />
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
</clearUsernameBinding>
</bindings>
But we received this error:
Unrecognized attribute 'maxReceivedMessageSize'.
How to change default message size using ClearUserNameBinding?
We found the solution following this steps:
http://sureshjakka.blogspot.com.ar/2010/03/changing-message-sizes-in.html
We modify the code of ClearUserNameBinding like this:
In AutoSecuredHttpTransportElement() constructor, initialize the values to maximum possible
public AutoSecuredHttpTransportElement()
{
MaxReceivedMessageSize = int.MaxValue;
MaxBufferSize = int.MaxValue;
MaxBufferPoolSize = long.MaxValue;
}
In CreateBindingElements() method create XMLDictionaryReaderQutotas object and set the same on TextMessageEncodingBindingElement. Here is the modified version of this method.
public override BindingElementCollection CreateBindingElements()
{
XmlDictionaryReaderQuotas rqMax = XmlDictionaryReaderQuotas.Max;
TextMessageEncodingBindingElement textBE = new TextMessageEncodingBindingElement();
textBE.MessageVersion = this.messageVersion;
rqMax.CopyTo(textBE.ReaderQuotas);
var res = new BindingElementCollection();
res.Add(textBE);
res.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement());
res.Add(new AutoSecuredHttpTransportElement());
return res;
}
Note: Make sure that you have "System.Runtime.Serialization" version 3.0.0.0 and above in your references. Because if you have version 2.0.0.0, you will get compile error as this version does not allow setting properties on ReaderQuotas.
Web.config:
<bindings>
<clearUsernameBinding>
<binding name="myClearUsernameBinding" />
</clearUsernameBinding>
</bindings>
Finally We update the references in server and client.

WCF service timing out when all timeout parameters set to maximum

I have a WCF service that has a very time consuming method that uploads large data files to "azure table storage".
I set my timeouts at runtime on the client side as follows:-
binding = new BasicHttpBinding();
binding.CloseTimeout = TimeSpan.FromMilliseconds(2147483647.0);
binding.OpenTimeout = TimeSpan.FromMilliseconds(2147483647.0);
binding.ReceiveTimeout = TimeSpan.FromMilliseconds(2147483647.0);
binding.SendTimeout = TimeSpan.FromMilliseconds(2147483647.0);
and my web.config has the timeouts set as follows:-
<bindings>
<basicHttpBinding>
<binding maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="22:30:00" receiveTimeout="22:30:00" openTimeout="22:30:00" closeTimeout="22:30:00" maxBufferSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
I'm running my code in VS 2012 and the problem i am seeing is that the file upload method crashes after 60 minutes with an unhandled CommunicationException: The remote server returned an error: NotFound. If i press F5, the upload continues and completes. The crash appears in the Reference.cs file at this point:-
public void EndFileUploadMethod(System.IAsyncResult result) {
object[] _args = new object[0];
base.EndInvoke("FileUploadMethod", _args, result);
I use similar azure blob to store my contents. my code doesn't have any timout setting. try this and let me know.
public static CloudBlobContainer Container
{
get
{
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
{
// Provide the configSetter with the initial value
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
RoleEnvironment.Changed += (sender, arg) =>
{
if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any((change) =>
(change.ConfigurationSettingName == configName)))
{
// The corresponding configuration setting has changed, so propagate the value
if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
{
// In this case, the change to the storage account credentials in the
// service configuration is significant enough that the role needs to be
// recycled in order to use the latest settings (for example, the
// endpoint may have changed)
RoleEnvironment.RequestRecycle();
}
}
};
});
CloudStorageAccount acc = CloudStorageAccount.FromConfigurationSetting("RecordingsStorageAccount");
CloudBlobClient bc = acc.CreateCloudBlobClient();
CloudBlobContainer c = bc.GetContainerReference(RoleEnvironment.GetConfigurationSettingValue("RecordingsContainer"));
return c;
}
}
For file uploads, there are a few other configurations that need to be in place. First, how large are the files you are trying to upload? If they are > 50MB or so, you might have to chunk them into smaller pieces and send the pieces over.
Before that, try adding the settings below to your config. Don't worry about the <authentication> and <compilation> tags. It is the <httpRuntime> and <requestLimits> tags that are of interest.
My maxAllowedContentLength attribute value is arbitrary below so you can set it to whatever you want. I believe it is measured in bytes.
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<authentication mode="Windows" />
<httpRuntime maxRequestLength="2147483647" />
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2000000000" />
</requestFiltering>
</security>
</system.webServer>

How to use ServiceRoutes while defining maxReceivedMessageSize for non-custom bindings in WCF

Editing this to refocus on the actual issue. I've preserved the origional question at the bottom of the message but changing the title and content to reflect what was really happening.
I need to override the maxReceivedMessageSize for a WCF service added to an MVC3 project via the ServiceRoute mechanism. Specifing the binding in the web.config doesn't work. How does one do this.
Initial question is below this line but is misleading based on lots of false positives I was seeing.
Hi I have used some examples to add a file streaming upload service to my MVC3 project. If I use the default bindings (i.e., not defined in web.config) the service works as long as I don't exceed the 64k default size. When I try and define my own binding to increase the size I get a content-type mismatch in my trace and a HTTP415 Unsupported Media Type in the response. I'm trying to call this via fiddler via HTTP and am not using a WCF client.
Here is the error in the trace:
Content Type image/jpeg was sent to a service expecting multipart/related;type="application/xop+xml". The client and service bindings may be mismatched.
Here is the web.config service model section
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="NewBehavior0" />
</endpointBehaviors>
</behaviors>
<services>
<service name="AvyProViewer.FileService">
<endpoint address="UploadFile" binding="basicHttpBinding" bindingConfiguration=""
contract="AvyProViewer.FileService" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<bindings>
<basicHttpBinding>
<binding name="NewBinding0" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Mtom" transferMode="StreamedRequest">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
Here is the service:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class FileService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadFile")]
public string UploadFile(Stream fileStream)
{
string path = HostingEnvironment.MapPath("~");
string fileName = Guid.NewGuid().ToString() + ".jpg";
FileStream fileToupload = new FileStream(path + "\\FileUpload\\" + fileName, FileMode.Create);
byte[] bytearray = new byte[10000];
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);
fileToupload.Write(bytearray, 0, bytearray.Length);
fileToupload.Close();
fileToupload.Dispose();
return fileName;
}
}
And here is where I expose it in my MVC3 routes:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new ServiceRoute("FileService", new WebServiceHostFactory(), typeof(FileService)));
. . .
}
I think the issue is with the mtom declaration for messageEncoding in your binding. Try changing messageEncoding to Text.
Answer ended up being a combination of three different stack overflow posts. None by themselves solved the question but each provided crucial clues as to what was happing.
It seems that if you add a ServiceRoute the web.config binding information is ignored. This SO post clued me in to what seems to be undocumented behavior of this function: Unable to set maxReceivedMessageSize through web.config
I then used this post to determine how to programatically override the maxreceivedmesssagesize for the binding: Specifying a WCF binding when using ServiceRoute.
Unfortunately the code form #2 didn't work out of the box (not sure if the binding behavior for ServiceRoute has changed or what makes the difference). Turns out that if you specify a ServiceRoute its automatically created as a CustomBinding which can't be cast to the WebHTTPBinding type used in #2. So this post: How to set the MaxReceivedMessageSize programatically when using a WCF Client? helped me determine how to change the code in #2 to add this capability to a custom binding.

How to create a WCF client without settings in config file?

I just start work on WCF a month ago. Please forgive me if I ask something already answered. I try to search first but found nothing.
I read this article, WCF File Transfer: Streaming & Chunking Channel Hosted In IIS. It works great. Now I like to integrate client side code to be part of my application, which is a dll running inside AutoCAD. If I want to work with config file, I have to change acad.exe.config which I don't think is a good idea. So I think if it possible, I want to move all code in config file to code.
Here is config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://10.1.13.15:88/WCFStreamUpload/service.svc/ep1"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService"
contract="MGFileServerClient.IService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
Could you please help me to make this change?
You can do all the setting up from within code, assuming that you don't need the flexibility to change this in the future.
You can read about setting up the endpoint on MSDN. Whilst this applies to the server the configuration of the endpoint and bindingd apply to the client as well, its just that you use the classes differently.
Basically you want to do something like:
// Specify a base address for the service
EndpointAddress endpointAdress = new EndpointAddress("http://10.1.13.15:88/WCFStreamUpload/service.svc/ep1");
// Create the binding to be used by the service - you will probably want to configure this a bit more
BasicHttpBinding binding1 = new BasicHttpBinding();
///create the client proxy using the specific endpoint and binding you have created
YourServiceClient proxy = new YourServiceClient(binding1, endpointAddress);
Obviously you'll probably want to configure the binding with security, timeouts etc the same as your config above (you can read about the BasicHttpBinding on MSDN), but this should get you going in the right direction.
This is totally code based configuration and working code. You dont need any configuration file for client. But at least you need one config file there (may be automatically generated, you dont have to think about that). All the configuration setting is done here in code.
public class ValidatorClass
{
WSHttpBinding BindingConfig;
EndpointIdentity DNSIdentity;
Uri URI;
ContractDescription ConfDescription;
public ValidatorClass()
{
// In constructor initializing configuration elements by code
BindingConfig = ValidatorClass.ConfigBinding();
DNSIdentity = ValidatorClass.ConfigEndPoint();
URI = ValidatorClass.ConfigURI();
ConfDescription = ValidatorClass.ConfigContractDescription();
}
public void MainOperation()
{
var Address = new EndpointAddress(URI, DNSIdentity);
var Client = new EvalServiceClient(BindingConfig, Address);
Client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;
Client.Endpoint.Contract = ConfDescription;
Client.ClientCredentials.UserName.UserName = "companyUserName";
Client.ClientCredentials.UserName.Password = "companyPassword";
Client.Open();
string CatchData = Client.CallServiceMethod();
Client.Close();
}
public static WSHttpBinding ConfigBinding()
{
// ----- Programmatic definition of the SomeService Binding -----
var wsHttpBinding = new WSHttpBinding();
wsHttpBinding.Name = "BindingName";
wsHttpBinding.CloseTimeout = TimeSpan.FromMinutes(1);
wsHttpBinding.OpenTimeout = TimeSpan.FromMinutes(1);
wsHttpBinding.ReceiveTimeout = TimeSpan.FromMinutes(10);
wsHttpBinding.SendTimeout = TimeSpan.FromMinutes(1);
wsHttpBinding.BypassProxyOnLocal = false;
wsHttpBinding.TransactionFlow = false;
wsHttpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
wsHttpBinding.MaxBufferPoolSize = 524288;
wsHttpBinding.MaxReceivedMessageSize = 65536;
wsHttpBinding.MessageEncoding = WSMessageEncoding.Text;
wsHttpBinding.TextEncoding = Encoding.UTF8;
wsHttpBinding.UseDefaultWebProxy = true;
wsHttpBinding.AllowCookies = false;
wsHttpBinding.ReaderQuotas.MaxDepth = 32;
wsHttpBinding.ReaderQuotas.MaxArrayLength = 16384;
wsHttpBinding.ReaderQuotas.MaxStringContentLength = 8192;
wsHttpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
wsHttpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;
wsHttpBinding.ReliableSession.Ordered = true;
wsHttpBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(10);
wsHttpBinding.ReliableSession.Enabled = false;
wsHttpBinding.Security.Mode = SecurityMode.Message;
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
wsHttpBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
wsHttpBinding.Security.Transport.Realm = "";
wsHttpBinding.Security.Message.NegotiateServiceCredential = true;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
wsHttpBinding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256;
// ----------- End Programmatic definition of the SomeServiceServiceBinding --------------
return wsHttpBinding;
}
public static Uri ConfigURI()
{
// ----- Programmatic definition of the Service URI configuration -----
Uri URI = new Uri("http://localhost:8732/Design_Time_Addresses/TestWcfServiceLibrary/EvalService/");
return URI;
}
public static EndpointIdentity ConfigEndPoint()
{
// ----- Programmatic definition of the Service EndPointIdentitiy configuration -----
EndpointIdentity DNSIdentity = EndpointIdentity.CreateDnsIdentity("tempCert");
return DNSIdentity;
}
public static ContractDescription ConfigContractDescription()
{
// ----- Programmatic definition of the Service ContractDescription Binding -----
ContractDescription Contract = ContractDescription.GetContract(typeof(IEvalService), typeof(EvalServiceClient));
return Contract;
}
}
Are you looking to retain your custom config and reference it within your application? You may try this article: Reading WCF Configuration from a Custom Location (In regards to WCF)
Otherwise, you can use ConfigurationManager.OpenExeConfiguration.

unable to load wcf restful help page after changing transferMode to "Streamed"

In my project, a wcf restful service, which allow users to upload photos to the web service.
After changing config settings to allow large file upload. (add binding configuration, i.e. "TransferMode", "BufferSize", etc.)
All Operation contracts are all working as expected.
However, the service help page for the endpoint stopped working.
The help page comes back, once I remove the binding config setting on my endpoint
How can I fixed this?? where did i missed
thank you all
<bindings>
<webHttpBinding>
<!-- buffer: 64KB; max size: 64MB -->
<binding name="StreamedBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transferMode="Streamed"
maxBufferPoolSize="67108864" maxBufferSize="65536" maxReceivedMessageSize="67108864">
</binding>
</webHttpBinding>
</bindings>
<service name="WCFRestFul.ApiRestful">
<endpoint address="" binding="webHttpBinding"
bindingConfiguration="StreamedBinding" bindingName="StreamedBinding"
contract="WCFRestFul.IApiRestful" behaviorConfiguration="web" />
</service>
Update:
I think it is not just because of the transfer mode, but maybe some other setting as well.
The service help page comes back once I remove the "bindingConfiguration" in the code above.
I have 2 endpoints. The other endpoint don't have the "bindingConfiguration", and the service help page works fine on that.
I definitely missed some thing here, maybe some thing simple.
any help will be greatly appreciated
I took carlosfigueira advice, painfully removed my config setting one at a time.
I changed my config settings from
OLD Code
<bindings>
<webHttpBinding>
<!-- buffer: 64KB; max size: 64MB -->
<binding name="StreamedBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transferMode="Streamed"
maxBufferPoolSize="67108864" maxBufferSize="65536" maxReceivedMessageSize="67108864">
</binding>
</webHttpBinding>
</bindings>
To Final working version (transferMode="Streamed" is removed)
<bindings>
<webHttpBinding>
<binding name="StreamedBinding" maxReceivedMessageSize="67108864" />
</webHttpBinding>
</bindings>
finally the service help page is back.
However I can't understand why it is back same as why it was turned off.
anyway, this is the working solution for my case.
hope someone would find it helpful.
What do you mean by saying that it stops working? In the example below the help page is still returned by the service (and I tried using both IE and Chrome, and they were able to see the page).
public class StackOverflow_5937029
{
[ServiceContract]
public interface ITest
{
[WebGet]
int Add(int x, int y);
}
public class Service : ITest
{
public int Add(int x, int y)
{
return x + y;
}
}
static void SendRequest(string address)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
req.Method = "GET";
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
foreach (string headerName in resp.Headers.AllKeys)
{
Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
}
Console.WriteLine();
Stream respStream = resp.GetResponseStream();
Console.WriteLine(new StreamReader(respStream).ReadToEnd());
Console.WriteLine();
Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
Console.WriteLine();
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
WebHttpBehavior behavior = new WebHttpBehavior
{
HelpEnabled = true
};
WebHttpBinding binding = new WebHttpBinding
{
TransferMode = TransferMode.Streamed
};
host.AddServiceEndpoint(typeof(ITest), binding, "").Behaviors.Add(behavior);
host.Open();
Console.WriteLine("Host opened");
SendRequest(baseAddress + "/Add?x=4&y=8");
SendRequest(baseAddress + "/help");
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}