Jak napisać „Html.BeginForm” w Razor

135

Jeśli napiszę tak:

form action = „Images” method = „post” enctype = „multipart / form-data”

to działa.

Ale w Razor z „@” to nie działa. Czy popełniłem jakieś błędy?

@using (Html.BeginForm("Upload", "Upload", FormMethod.Post, 
                             new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(true)

    <fieldset>

        Select a file <input type="file" name="file" />
        <input type="submit" value="Upload" />

    </fieldset>
}

Mój kontroler wygląda tak:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Upload() 
{
    foreach (string file in Request.Files)
    {
        var uploadedFile = Request.Files[file];
        uploadedFile.SaveAs(Server.MapPath("~/content/pics") + 
                                      Path.GetFileName(uploadedFile.FileName));
    }

    return RedirectToAction ("Upload");
}
kk-dev11
źródło
Czy działanie to faktycznie „obrazy” czy „Prześlij / Prześlij”?
J. Steen
właściwie mam dwa kontrolery. kontroler obrazu z akcją „image” .. i upload controller ”z akcją upload ..
kk-dev11

Odpowiedzi:

202

Poniższy kod działa dobrze:

@using (Html.BeginForm("Upload", "Upload", FormMethod.Post, 
                                      new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(true)
    <fieldset>
        Select a file <input type="file" name="file" />
        <input type="submit" value="Upload" />
    </fieldset>
}

i generuje zgodnie z oczekiwaniami:

<form action="/Upload/Upload" enctype="multipart/form-data" method="post">    
    <fieldset>
        Select a file <input type="file" name="file" />
        <input type="submit" value="Upload" />
    </fieldset>
</form>

Z drugiej strony, jeśli piszesz ten kod w kontekście innej konstrukcji po stronie serwera, takiej jak iflub foreach, powinieneś usunąć @przed using. Na przykład:

@if (SomeCondition)
{
    using (Html.BeginForm("Upload", "Upload", FormMethod.Post, 
                                      new { enctype = "multipart/form-data" }))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            Select a file <input type="file" name="file" />
            <input type="submit" value="Upload" />
        </fieldset>
    }
}

Jeśli chodzi o kod po stronie serwera, oto jak postępować :

[HttpPost]
public ActionResult Upload(HttpPostedFileBase file) 
{
    if (file != null && file.ContentLength > 0) 
    {
        var fileName = Path.GetFileName(file.FileName);
        var path = Path.Combine(Server.MapPath("~/content/pics"), fileName);
        file.SaveAs(path);
    }
    return RedirectToAction("Upload");
}
Darin Dimitrov
źródło
1
dzięki. Spójrz na kontroler, który zaktualizowałem w moim pytaniu. Nie działa z kodem Razor ..
kk-dev11
2
@ user1076915, co to znaczy nie działa ? Czy mógłbyś być trochę bardziej szczegółowy. Zaktualizowałem moją odpowiedź przykładowym kodem pokazującym, jak może wyglądać akcja kontrolera. Jeśli nie możesz pobrać przesłanego pliku w akcji kontrolera, może to oznaczać, że masz zagnieżdżone <form>tagi (co jest niedozwolone w HTML) lub możesz używać javascript, który przechwytuje normalne przesyłanie formularza i wykonuje żądanie AJAX, które nie robi t pracować z przesyłaniem plików.
Darin Dimitrov
Użyłem Twojej akcji kontrolera i brzytwy „@using” .. ale wyświetla się -> Opis: HTTP 404. Poszukiwany zasób (lub jedna z jego zależności) mógł zostać usunięty, zmieniono jego nazwę lub jest chwilowo niedostępny. Przejrzyj następujący adres URL i upewnij się, że jest wpisany poprawnie.
kk-dev11
@ user1076915, kiedy pojawia się ten komunikat o błędzie? Kiedy chcesz wyrenderować formularz do przesłania lub kiedy wysyłasz formularz? W pierwszym przypadku upewnić się, że masz GETUpload działań, które będą służyć Upload.cshtmlwidok zawierający ten kod: public ActionResult Upload() { return View(); }. Upewnij się więc, że masz kontroler o nazwie, który UploadControllerzawiera dwie akcje przesyłania: jedną do obsługi formularza, a drugą do przetwarzania przesłania.
Darin Dimitrov
2
Działa, ale w kontekście POST sugeruję dodać: @ Html.AntiForgeryToken ();
Frédéric De Lène Mirouze