2010-02-10 15 views
13

Setup:ASP.NET MVC Controller FileContent ActionResult nazywane za pośrednictwem AJAX

Kontroler zawiera metodę public ActionResult SaveFile() która zwraca FileContentResult.

Co działa:

Widok zawiera formularz, który składa do tej akcji. Rezultatem jest to dialog: enter image description here

Co nie działa:

Widok zawiera pewne javascript, aby wykonać połączenie AJAX do tego samego działania regulatora, gdzie forma będzie publikować. Zamiast wywoływania wyżej wymienionego okna dialogowego lub nawet funkcji powodzenia AJAX, odpowiedź wyzwala funkcję błędu AJAX, a odpowiedź XMLHttpRequest.responseText zawiera odpowiedź pliku.

Co muszę zrobić:

Złóż wniosek o pliku przy użyciu AJAX i skończyć z tym samym skutkiem jak przy składaniu formularza. Jak mogę uczynić żądanie AJAX podać okno dialogowe, które pokazuje formularz?

+0

Dlaczego nie można po prostu użyć non-ajax rozmowy? – LukLed

+0

Mogę, ale chcę wykonać inne przetwarzanie w funkcji javaScript po zakończeniu składowania, na przykład odblokować formularz, który zablokowałem przed zapisaniem. – Rick

+0

OK, więc możesz najpierw wywołać ajax SaveFile. SaveFile zwróci true/false. Kiedy zwraca true, wywołujesz nie-ajax GET, aby pobrać plik. – LukLed

Odpowiedz

16

Oto szybki przykład, który wymyśliłem. Jest to koncepcja, o której opowiadał LukLed z wywołaniem SaveFile, ale nie zwraca zawartości pliku przez ajax i zamiast tego przekierowuje do pobrania.

Oto kod Widok:

<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    $(function() { 
     // hide form code here 

     // upload to server 
     $('#btnUpload').click(function() { 
      $.ajax({ 
       type: 'POST', 
       dataType: 'json', 
       url: '<%= Url.Action("SaveFile", "Home") %>', 
       success: function(fileId) { 
        window.location = '<%= Url.Action("DownloadFile", "Home") %>?fileId=' + fileId; 
       }, 
       error: function() { 
        alert('An error occurred uploading data.'); 
       } 
      }); 
     }); 
    }); 
</script> 

<% using (Html.BeginForm()) { %> 

    <div>Field 1: <%= Html.TextBox("field1") %></div> 

    <div>Field 2: <%= Html.TextBox("field2") %></div> 

    <div>Field 3: <%= Html.TextBox("field3") %></div> 

    <button id="btnUpload" type="button">Upload</button> 

<% } %> 

Oto kod kontrolera:

[HandleError] 
public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 

    public JsonResult SaveFile(string field1, string field2, string field3) 
    { 
     // save the data to the database or where ever 
     int savedFileId = 1; 

     // return the saved file id to the browser 
     return Json(savedFileId); 
    } 

    public FileContentResult DownloadFile(int fileId) 
    { 
     // load file content from db or file system 
     string fileContents = "field1,field2,field3"; 

     // convert to byte array 
     // use a different encoding if needed 
     var encoding = new System.Text.ASCIIEncoding(); 
     byte[] returnContent = encoding.GetBytes(fileContents); 

     return File(returnContent, "application/CSV", "test.csv"); 
    } 

    public ActionResult About() 
    { 
     return View(); 
    } 
} 
+0

Nate, dziękuję za dostarczenie tak szczegółowego przykładu. Doceniam to, a także dziękuję LukLed za staranne wyjaśnienie swojego rozwiązania. Punktem, który nie był zatonięciem, było to, że pierwsze połączenie przygotowało dane do zapisania, a drugie wywołanie pobiera. – Rick

+0

Byłem tam przed uderzeniem głową w ścianę, mówiąc WTF do siebie, próbując zrozumieć, bez zmartwień. Miło, że mogłem pomóc. –

Powiązane problemy