MindFresher
MindFresher

Reputation: 740

File Upload to a cross domain WCF service using jquery ajax

Here is what I am trying to do (unsuccessfully, I might add) and would appreciate any direction you can give me

From my HTML5 site, I want to upload a file to a cross domain WCF service that is hosted in IIS 7.5.

In addition to uploading the files, I need to send additional parameters to the upload function on the server

Is this possible to do?

Here is what my operationContract looks like:

[OperationContract]
[WebInvoke( Method = "POST",
UriTemplate = "/uploadmodeldata/?id={Id}&customerdatatype={customerdatatype}&data={data}")]
void UploadModelData(string Id, string customerdataType, byte[] data);

Here is what my jquery ajax request

function FileVisits() {

    var uid = checkCookie1();
    userid = uid.toString().replace(/"/g, '');
    var fileData = JSON.stringify({
   Id:userid ,customerdatatype:scanupload,
        data: $('#fileBinary').val()
    });
    alert(fileData);
        "use strict";
        var wcfServiceUrl = "http://xxxxx:1337/Service1.svc/XMLService/";
        $.ajax({
            cache: false,
            url: wcfServiceUrl + "uploadmodeldata/",               
            data: fileData,
            type: "POST",
            processData: false,
            contentType: "application/json",
            timeout: 10000,
            dataType: "json",
            headers:    {
                        'User-agent': 'Mozilla/5.0 (compatible) Greasemonkey',
                        'Accept': 'application/atom+xml,application/xml,text/xml',
                    },
            beforeSend: function (xhr) {
                $.mobile.showPageLoadingMsg();

                xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");


            },
            complete: function () {
                $.mobile.hidePageLoadingMsg();
            },

            success: function (data) {
                var result = data;


            },
            error: function (data) {
                alert("Error");
            }
        });

}

if file size is less then 100 kb this error occurred

Method not allowed

but if file is greater then 100 kb this error occurred

413 Request entity to large

How can I upload a file from jquery ajax to cross domain wcf. Thanks

Upvotes: 2

Views: 3872

Answers (3)

Marcelo Rodrigues
Marcelo Rodrigues

Reputation: 41

The problem is with the "POST". To solve the problem do the following

Create a Global.asax and add following to enable Ajax cross-domain POST.

 public void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST,OPTIONS");

            if ((HttpContext.Current.Request.HttpMethod == "OPTIONS"))
            {

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }
    }

Upvotes: 0

Cristian Oprea
Cristian Oprea

Reputation: 71

It took me a lot of work but here is my code(in case someone needs it):

$("#UploadFileBtn").click(function () {     
    fileName = document.getElementById("filePicker").files[0].name;
    fileSize = document.getElementById("filePicker").files[0].size;
    fileType = document.getElementById("filePicker").files[0].type;     
    var file = document.getElementById("filePicker").files[0];
    if (file) {
    // create reader
    var reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = function(e) {
        var content = e.target.result;
        content = content.substring(content.indexOf('64') + 3);
        bhUploadRequest = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
                                             "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" " + 
                                             "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
                                             "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
                             "<SOAP-ENV:Header>"+
                                "<m:FileName xmlns:m=\"http://tempuri.org/\">" + fileName + "</m:FileName>" +
                                "<m:Length xmlns:m=\"http://tempuri.org/\">" + fileSize + "</m:Length>" +
                             "</SOAP-ENV:Header>" +
                             "<SOAP-ENV:Body>" +
                                "<m:RemoteFileInfo xmlns:m=\"http://tempuri.org/\">" +
                                    "<m:FileByteStream>" + content + "</m:FileByteStream>" +
                                "</m:RemoteFileInfo>" +
                             "</SOAP-ENV:Body>" +
                         "</SOAP-ENV:Envelope>";

        $.ajax({
            type: "POST",
            async: true,
            url: wsFtransferUrl,
            data: bhUploadRequest,
            timeout: 10000,
            contentType: "text/xml",
            crossDomain: true,
            beforeSend: function (xhr) {
                xhr.setRequestHeader("SOAPAction", "http://tempuri.org/IFileTransferService/UploadFile");
                xhr.setRequestHeader("TICKET", Ticket);
            },              
            success: function (data) {
            alert('succes');
                $(data).find("UploadFileResponse").each(function () {
                    alert($(this).find("UploadFileResult").text());
                });
            },
            error: function (xhr, status, error) {
                alert('error:' + error);
            }
        });

    };
}
    return;

    });

and here is my WCF transfer service:

public void UploadFile(RemoteFileInfo request)
        {   
            string filePath = string.Empty;
            string guid = Guid.NewGuid().ToString();
            int chunkSize = 1024;
            byte[] buffer = new byte[chunkSize];
            long progress = 0;

            filePath = Path.Combine(uploadFolder, request.FileName);

            if (File.Exists(filePath))
                File.Delete(filePath);

            using (FileStream writeStream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write))
            {
          do
                {
                    // read bytes from input stream
                    int bytesRead = request.FileByteStream.Read(buffer, 0, chunkSize);
                    if (bytesRead == 0)
                        break;
                    progress += bytesRead;                    
                    // write bytes to output stream
                    writeStream.Write(buffer, 0, bytesRead);
                }
                while (true);
            }
        }

Upvotes: 1

nunespascal
nunespascal

Reputation: 17724

You are getting the Method not allowed cause you are trying to call a service on another domain. This violates the Same origin policy. This is a security limitation. Most older browsers will deny such requests.

You will need to setup Cross-Origin Resource Sharing if you want to access a different domain the webservice in javascript.

Cross-origin resource sharing (CORS) is a mechanism that allows a web page to make XMLHttpRequests to another domain. Such "cross-domain" requests would otherwise be forbidden by web browsers, per the same origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request

If you have access to the webservice code, you can enable CORS requests at the server.
Enable cors is a good resource. Here is some explaination on cors

On IIS 7, you need to set a few custom headers in your web.config.

<system.webserver>
 <httpprotocol>
  <customheaders>
   <add name="Access-Control-Allow-Origin" value="*" />
   <add name="Access-Control-Allow-Headers" value="Content-Type" />
  </customheaders>
 </httpprotocol>
</system.webserver>

Here are the steps for IIS6

As for the 413 error, that is related to the max file size you allow on your binding

<bindings>
    <webHttpBinding>
      <binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
    </webHttpBinding>
</bindings>

Upvotes: 0

Related Questions