2013-04-17 123 views
1

我知道有很多問題類似於這個問題上的礦,但那些不能解決我的問題。我知道web服務自然將我的對象解析爲json作爲框架的一部分。我已手動設置請求標頭Accept爲'application/json,text/javascript,/; Q = 0.01' 。我已將<ScriptMethod(ResponseFormat:=ResponseFormat.Json)>添加到我的網絡服務中。asmx Web服務無法返回JSON與FineUploader文件上傳

很明顯,我的Web服務正在用文本/純文本響應來響應文件上傳請求標題,並解析了我的簡單FineUploaderResponse對象失敗。請記住,對同一個Web服務的常規jQuery AJAX調用可以正常工作。我寧願不使用Web API或通用處理程序代替我的網站,因爲多個網站依賴於我的框架並期望此標準。

在此先感謝!

代碼:

Public Class FineUploaderResponse 
     Property Success As Boolean 
    End Class 

<WebMethod(EnableSession:=True)> _ 
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _ 
Public Function UploadPhotos() 
    'next three lines are pointless, didn't help 
    'HttpContext.Current.Response.Clear() 
    'HttpContext.Current.Response.ContentType = "application/json" 
    'HttpContext.Current.Response.Charset = "utf-8" 

    Dim response As New FineUploaderResponse() 
    response.Success = True 

    Return response 

End Function 

當然現在這個Web服務工作,如果我這樣做:

$(document).ready(function() { 
      $.ajax(
      { 
       url: "/Services/PhotosService.asmx/UploadPhotos", 
       type: "POST", 
       contentType: "application/json; charset=utf-8", 
       dataType: "json", 
       success: function (data) { 
        console.log(data.d); 
       } 

      }); 

     }); 

標準的jQuery請求頭

POST http://localhost:3066/Services/PhotosService.asmx/UploadPhotos HTTP/1.1 
Host: localhost:3066 
Proxy-Connection: keep-alive 
Content-Length: 0 
Cache-Control: no-cache 
Pragma: no-cache 
Origin: http://localhost:3066 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31 
Content-Type: application/json; charset=utf-8 
Accept: application/json, text/javascript, */*; q=0.01 
X-Requested-With: XMLHttpRequest 
Referer: http://localhost:3066/Test.aspx 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

但是我使用FineUploader併發布Content-Type:multipart/form-data;公告雖然接受頭是兩個jQuery的AJAX和FineUploader請求相同的:

POST http://localhost:3066/Services/PhotosService.asmx/UploadPhotos HTTP/1.1 
Host: localhost:3066 
Proxy-Connection: keep-alive 
Content-Length: 110634 
Cache-Control: no-cache 
Pragma: no-cache 
Origin: http://localhost:3066 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31 
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary449tHPTKEpuO5jOR 
Accept: application/json, text/javascript, */*; q=0.01 
X-Requested-With: XMLHttpRequest 
Referer: http://localhost:3066/Sellers/photos/?pid=37344 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

從標準的jQuery AJAX調用Web服務的響應是:

HTTP/1.1 200 OK 
Server: ASP.NET Development Server/10.0.0.0 
Date: Wed, 17 Apr 2013 00:12:21 GMT 
X-AspNet-Version: 4.0.30319 
Cache-Control: private, max-age=0 
Content-Type: application/json; charset=utf-8 
Content-Length: 22 
Connection: Close 

從FineUploader上傳到Web服務響應文件請求是:

HTTP/1.1 500 Internal Server Error 
Server: ASP.NET Development Server/10.0.0.0 
Date: Wed, 17 Apr 2013 00:18:26 GMT 
X-AspNet-Version: 4.0.30319 
Cache-Control: private 
Content-Type: text/plain; charset=utf-8 
Content-Length: 1936 
Connection: Close 

內部服務器500的錯誤的錯誤消息細節爲:

System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type Kazork.AppCode.PhotosService+FineUploaderResponse was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. 
    at System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(String name, String ns, Object o, Boolean xsiType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write3_anyType(Object o) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.ObjectSerializer1.Serialize(Object objectToSerialize, XmlSerializationWriter writer) 
    at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id) 
    --- End of inner exception stack trace --- 
    at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id) 
    at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces) 
    at System.Web.Services.Protocols.XmlReturnWriter.Write(HttpResponse response, Stream outputStream, Object returnValue) 
    at System.Web.Services.Protocols.HttpServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream) 
    at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues) 
    at System.Web.Services.Protocols.WebServiceHandler.Invoke() 

而且,如果你很好奇,這是我的電話FineUploader:

var uploader = new qq.FineUploader({ 
      element: document.getElementById('bootstrapped-fine-uploader'), 
      request: { 
       endpoint: "/Services/PhotosService.asmx/UploadPhotos", 
       forceMultipart: true, 
       params: { propertyId:<%=PropertyId %>}, 
       customHeaders: { Accept: 'application/json, text/javascript, */*; q=0.01' } 
      }, 
      text: { 
       uploadButton: '<i class="icon-upload icon-white"></i>Upload nice images.' 
      }, 
      template: '<div class="qq-uploader">' + 
         '<pre class="qq-upload-drop-area"><span>{dragZoneText}</span></pre>' + 
         '<div class="qq-upload-button btn btn-success" style="width: auto;">{uploadButtonText}</div>' + 
         '<span class="qq-drop-processing"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></span>' + 
         '</div>' + 
         '<ul class="qq-upload-list" style="margin-top: 10px; text-align: center;"></ul>' + 
         '', 
      classes: { 
       success: 'alert alert-success', 
       fail: 'alert alert-error' 
      }, 
      debug: false, 
      callbacks: { 
//    onComplete: function (id, fileName, responseJson) { 
//     $.when(loadThumbs()).done(function() { 
//      $(".qq-upload-list > .alert-success").remove(); 
//     }); 
//     toastr.success("Success!"); 
//    }, 
       onComplete: function(id, fileName, responseJSON) { 
         if (responseJSON.success) { 
         $('#file-' + id).removeClass('alert-info') 
             .addClass('alert-success') 
             .html('<i class="icon-ok"></i> ' + 
               'Successfully saved ' + 
               '「' + fileName + '」' + 
               '<br><img src="/images/message_ok.png" alt="' + fileName + '">'); 

          $.when(loadThumbs()).done(function() { 
           $(".qq-upload-list > .alert-success").remove(); 
          }); 
          toastr.success("Success!"); 
         } else { 
         $('#file-' + id).removeClass('alert-info') 
             .addClass('alert-error') 
             .html('<i class="icon-exclamation-sign"></i> ' + 
               'Error with ' + 
               '「' + fileName + '」: ' + 
               responseJSON.error); 
         } 
       }, 
       onError: function (id, fileName, errorReason) { 
        toastr.error("Failed! Try again."); 
       } 
      } 
     }); 

回答

1

好簡單的辦法,雖然令人沮喪,Web服務殺了我很多時間試圖維持一個現代的Web應用程序。但我現在不需要遷移到Web API,主要是因爲我的Web應用程序依賴於會話(您可以將會話引入Web API,但顯然不是RESTful)。

所以我取代了FineUploaderResponse類用我自己的JSON格式的響應:

<WebMethod(EnableSession:=True)> _ 
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _ 
Public Sub UploadPhotos() 

    Context.Response.Write(New ResultData().GetResultDataJSON("success", "true")) 

End Sub 


    Public Function GetResultDataJSON(key As String, value As String) As String 
     Dim oBuilder As StringBuilder = New StringBuilder() 
     oBuilder.Append("{") 
     oBuilder.AppendFormat("""{0}"" : {1}", key, value) 
     oBuilder.Append("}") 
     Return oBuilder.ToString() 
    End Function 

這裏是我的FineUploader的Javascript:

/*=================================================*/ 
//fineUploaderInitialize 
/*=================================================*/ 
    function createUploader() { 
     var uploader = new qq.FineUploader({ 
      element: document.getElementById('bootstrapped-fine-uploader'), 
      request: { 
       endpoint: "/Services/PhotosService.asmx/UploadPhotos", 
       forceMultipart: true, 
       params: { propertyId:$('#hiddenPropertyIdUploadPhotosUserControl').val()}, 
       customHeaders: { Accept: 'application/json, text/javascript, */*; q=0.01' }, 
       allowedExtensions: ['gif', 'jpeg', 'jpg', 'png'], 
      }, 
      text: { 
       uploadButton: 'Drag & drop photos into this area or CLICK HERE to upload photos' 
      }, 
      template: '<div class="qq-uploader text-center" style="height:70px;background-color:white;border-radius:6px;">' + 
         '<div class="qq-upload-button btn btn-success col-lg-12">{uploadButtonText}</div>' + 
         '<span class="qq-drop-processing"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></span>' + 
         '<pre class="qq-upload-drop-area"><span>{dragZoneText}</span></pre>' + 
         '</div>' + 
         '<ul class="qq-upload-list" style="margin-top: 10px; text-align: center;"></ul>' + 
         '', 
      classes: { 
       success: 'alert alert-success', 
       fail: 'alert alert-error' 
      }, 
      debug: false, 
      callbacks: { 
       onComplete: function(id, fileName, responseJSON) { 
        if (responseJSON.success) { 
         $('#file-' + id).removeClass('alert-info') 
             .addClass('alert-success') 
             .html('<i class="glyphicon glyphicon-ok"></i> ' + 
               'Successfully saved ' + 
               '「' + fileName + '」' + 
               '<br><img src="/images/message_ok.png" alt="' + fileName + '">'); 
         $.when(loadThumbs()).done(function() { 
          $(".qq-upload-list > .alert-success").remove(); 
         }); 
         toastr.success("Success!"); 
        } else { 
         $('#file-' + id).removeClass('alert-info') 
             .addClass('alert-error') 
             .html('<i class="glyphicon glyphicon-exclamation-sign"></i> ' + 
               'Error with ' + 
               '「' + fileName + '」: ' + 
               responseJSON.error); 
        } 
       }, 
       onError: function (id, fileName, errorReason) { 
        if(errorReason == 'XHR returned response code 0'){ 
         toastr.error('File Size Cannot Exceed 20 Megabytes'); 
        }else{ 
         toastr.error(errorReason); 
        } 
       } 
      } 
     }); 
    } 
/*=================================================*/