24

olarak ayarlandığında ASP.NET MVC dosya modeli bağlama yayımlandı ASP.NET MVC model bağlamada özel bir model ciltleyicide istek içeriğine manüel olarak bakmadan postalanan dosyalara (<input type="file" />) sahip olmanın bir yolu var mı ve giriş olarak sadece kayıtlı bir dosyayı alan ayrı bir işlem yöntemi oluşturmadan?Parametre model

Bu işe olacağını sanırdım:

class MyModel { 
    public HttpPostedFileBase MyFile { get; set; } 
    public int? OtherProperty { get; set; } 
} 

<form enctype="multipart/form-data"> 
    <input type="file" name="MyFile" /> 
    <input type="text" name="OtherProperty" /> 
</form> 

public ActionResult Create(MyModel myModel) { ... } 

Fakat yukarıdaki senaryoyu göz önüne alındığında, MyFile bağlayıcı bağlamında değer sağlayıcı değerlerin bile bir parçası değildir. (. OtherProperty elbette,) Ama eğer bunu yaparsam çalışır:

Yani
public ActionResult Create(HttpPostedFileBase postedFile, ...) { ... } 

, neden hiçbir parametre bir modeldir ortaya bağlayıcı gelmez ve bunu çalışmasını nasıl sağlayabilirsiniz? Özel model bir bağlayıcı kullanmayla ilgili bir sorunum yok, ancak bunu özel bir modelde Request.Files["MyFile"]'a bakmadan nasıl yapabilirim?

Tutarlılık, netlik ve test edilebilirlik için, kodumun, istek bağlamını manuel olarak incelemeden, yayınlanan dosyalarla ilişkili olanlar da dahil olmak üzere, bir modeldeki tüm özelliklerin otomatik olarak bağlanmasını sağlamak istiyorum. Şu anda the approach Scott Hanselman wrote about kullanarak model bağlama test ediyorum. Veya bu konuda yanlış bir şekilde mi gidiyorum? Bunu nasıl çözeceksin? Ya da Request.Form ve Request.Files arasındaki ayrılık geçmişinden dolayı bu tasarım ile mümkün değil mi?

cevap

29

Bu nedenle ValueProviderDictionary tek model bağlama bağlamında değer sağlayıcı sözlüğü doldurmak için Request.Form, RouteData ve Request.QueryString görünüyor olmasıdır çıkıyor. Bu nedenle, özel bir model bağlayıcının, dosya koleksiyonunu doğrudan talep bağlamında incelemeksizin, modele katılmaya katılabilmesi için gönderilmiş dosyalara izin vermenin bir yolu yoktur.Sürece myModelFile aslında file giriş formu alanın adıdır olarak

public ActionResult Create(MyModel myModel, HttpPostedFileBase myModelFile) { } 

, herhangi bir özel şeyler için gerek yoktur: Bu aynı şeyi başarmak saptadığımız en yakın yoldur.

+5

* Not; Eğer yalaka olma önce tam ve dikkatli bir şekilde soruyu okursanız –

+0

Aynı kullanmak var ama hata var: - birden çok parametre bağlama olamaz, benim $ .ajax i belirledik: - türü: 'POST', dataType: 'json', contentType: 'çok parçalı/form-data' , data: formData – ujjaval

6

the one you linked to (another one ... aracılığıyla) 'a bağlandığı this post'a baktınız mı?

Değilse, oldukça basit görünüyor.

public class HttpPostedFileBaseModelBinder : IModelBinder { 
    public ModelBinderResult BindModel(ModelBindingContext bindingContext) { 
     HttpPostedFileBase theFile = 
      bindingContext.HttpContext.Request.Files[bindingContext.ModelName]; 
     return new ModelBinderResult(theFile); 
    } 
} 

O şöyle Global.asax.cs bunu kaydeder:

<form action="/File/UploadAFile" enctype="multipart/form-data" method="post"> 
    Choose file: <input type="file" name="theFile" /> 
    <input type="submit" /> 
</form> 

Tümü: şöyle bir form ile

ModelBinders.Binders[typeof(HttpPostedFileBase)] = 
    new HttpPostedFileBaseModelBinder(); 

ve mesajları Bu kullandığı modeli bağlayıcı olduğunu kod doğrudan blog yazısı üzerinden kopyalanır ...

+0

Aslında şu an kullandığım yaklaşım budur. Fakat bu yaklaşımla ilgili iki sorun var: 1; istemediğim istek bağlamını (bindingContext.HttpContext.Request aracılığıyla) kullanır ve 2; yalnızca gönderinin sadece yüklenen bir dosyadan oluştuğu bir senaryoyu ele alır (bu elbette kolayca değiştirilebilir). – bzlm

+0

Ayrıca, BindModel (ModelBindingContext bindingContext), yayın öncesi koduna benziyor. Orada da bir ControllerContext var. – bzlm

+1

MVC Framework kaynak koduna bir göz attınız mı? "Normal" model bağlayıcıların nasıl çalıştığından emin değilim, ancak yol boyunca HttpContext.Current.Request.Form [] koleksiyonunu * kullanmadan * form değerlerini nasıl yakalayabileceğinizi gerçekten göremiyorum. ... http://weblogs.asp.net/scottgu/archive/2008/03/21/asp-net-mvc-source-code-now-available.aspx –

-16

Sen HttpPostedFileBase çerçevesinde varsayılan olarak tescil edilmiştir, özel bir bağlayıcı kayıt gerekmez:

public ActionResult Create(HttpPostedFileBase myFile) 
{ 
    ... 
} 

yerine bloglar ve web forumları dayanmak arasında, bir kez süre her read a book yardımcı olur.

+0

Sorguyu, yayınlanan bir dosyayı tek parametresi olarak alan bir eylem yöntemi istemediğim gerçeğini daha açık olarak belirledim. Gönderilen dosya, modeldeki birçok özellikten yalnızca biri ise aynı şeyi gerçekleştirmenin bir yolu var mı? (Bu arada diğer ASP.NET MVC kitabım var.) – bzlm

+0

Doğru cevap bu; Aynı problemi tekrar yaşadım. HttpPostedFileBase bağlanır, ancak HttpPostedFile olmaz. –

+0

Hayır, HttpPostedFileBase varsayılan model bağlayıcıda standart değer sağlayıcı bağlayıcısını kullanarak bağlanmayacaktır. Yine de, bu cevapta yönteme bağlanacaktır. * Formdaki 'enctype' niteliğini göz ardı etmeyin:) – bzlm

14

bir başka yolu girişi ile aynı ada sahip gizli bir alan eklemektir:

<input type="hidden" name="MyFile" id="MyFileSubmitPlaceHolder" /> 

DefaultModelBinder sonra bir alan görmek ve doğru bağlayıcı yaratacaktır.

+2

ASP.NET MVC 2 RC, gizli alan olmadan bunu ele alır gibi görünüyor. –

+0

kesinlikle doğru, ASP.NET MVC 2 kullanıyorum ve dosya dosyamı herhangi bir ekstra çalışma yapmadan modelime başarılı bir şekilde bağlayabiliyorum. Fantastik! – Pandincus