c# - Asp.net MVC - Model Binding Only Working with Primitive Values -


i building web application storing data form in database. initial approach create custom model/class, , have post data bind it. approach had used before successfully. however, time not work. no matter did, not values bind property of object (ie model.title), primitive values (ie string title). in frustration, decided bind data primitives.

however, while of data correctly bound, have ran difficulty - data not being bound httppostedfilebase object. initially, had assumed there might have been wrong custom class. no longer appears case, instead model binder no longer seems able bind correctly any object, primitives.

my view

@model storywall.viewmodels.addstoryviewmodel @{     viewbag.title = "add new story"; }    <form  method="post" enctype="multipart/form-data" name="addstoryform" action="add/submitstory" novalidate class="form-horizontal">     @html.antiforgerytoken()       <div class="form-group"><label class="control-label col-sm-2">story title</label><div class="col-sm-10"><input type='text' class="form-control" ng-model="title" name="posttitle" required /> <span class="text-danger" ng-show="addstoryform.model.posttitle.$touched && addstoryform.model.posttitle.$invalid">title required.</span></div></div>      <div class="form-group"><label class="control-label col-sm-2">story</label><div class="col-sm-10"><textarea class="form-control" ng-model="body" name="postbody" required> </textarea> <span class="text-danger" ng-show="addstoryform.postbody.$touched && addstoryform.postbody.$invalid">field required.</span></div></div>        <div class="form-group"><label class="control-label col-sm-2">store / location </label><div class="col-sm-10"><select name="storeid" class="form-control" ng-model="store" required > <option value="">select...</option>          @foreach (var store in @model.stores)         {             <option value="@store.storeid">@store.storename</option>         }         </select>          <span class="text-danger" ng-show="addstoryform.storeid.$touched && addstoryform.storeid.$invalid">please select store.</span></div></div>      <div class="form-group"><label class="control-label col-sm-2">add picture (optional)</label><div class="col-sm-10"><input type="file" class="form-control" name="storyimg"></div></div>      <div class="form-group"><label class="control-label col-sm-2">your name</label><div class="col-sm-10"><input type='text' class="form-control" ng-model="author" name="authorname" required /> <span class="text-danger" ng-show="addstoryform.authorname.$touched && addstoryform.authorname.$invalid">please enter name.</span></div></div>      <div class="form-group"><label class="control-label col-sm-2">your email</label><div class="col-sm-10"><input type='email' class="form-control" ng-model="email" name="authoremail" required /> <span class="text-danger" ng-show="addstoryform.authoremail.$dirty && addstoryform.authoremail.$invalid">please enter email.</span></div></div>       <div ng-controller="tagsctrl" class="form-group">         <label class="control-label col-sm-2">tags (separate comma) {{tags.text}}</label>         <tags-input on-tag-added="updateinput()" ng-model="tags"></tags-input>              <div class="col-sm-10"><input type='text' class="form-control" ng-model="input.currtext" id="tags" name="tagtext" /> </div>      </div>      <button type="submit" class="btn btn-primary" ng-disabled="addstoryform.$invalid">submit</button> </form> 

the controller responsible generating view above , accepting post data:

  public class addcontroller : controller {      storymodel dbcontext = new storymodel();      public actionresult index()     {       addstoryviewmodel vm = new addstoryviewmodel();         vm.stores = dbcontext.stores.orderby(s => s.storename).tolist();          return view("index", vm);     }      [httppost]     [validateantiforgerytoken]     public actionresult submitstory(string tagtext, string postbody, string posttitle, int storeid, string authoremail, string authorname, httppostedfile storyimg)      {              story newstory = new story();              // create new tag if necessary             string[] tags = tagtext.split(',');              if (tags.length > 0) {                 (int = 0; < tags.length; i++)                 {                     string tagtext = tags[i].tolower();                     tag tag = dbcontext.tags.firstordefault(t => t.tagname.tolower() == tagtext);                     if (tag != null)                     {                         newstory.tags.add(tag);                     }                     else                     {                         tag newtag = new tag();                         newtag.tagname = tags[i].tolower();                         dbcontext.tags.add(newtag);                         dbcontext.savechanges();                         newstory.tags.add(tag);                      }                 }             }              newstory.storybody = postbody;             newstory.dateposted = datetime.now;             newstory.posteremail = authoremail;             newstory.postername = authorname;             newstory.title = posttitle;             newstory.storeid = storeid;              // upload image if uploaded              if (storyimg != null)             {                 string filename = string.format("{0}.jpg", new guid());                 storyimg.saveas(server.mappath("~/img/") + filename);                 newstory.storyimage = filename;                      }             dbcontext.stories.add(newstory);             dbcontext.savechanges();             return redirecttoaction("success", new { storyid = newstory.storyid });      }      public actionresult success(int32 storyid)     {         successviewmodel vm = new successviewmodel();         vm.newstoryid = storyid;          return view(vm);      } } 

}

the non-primitive, storyimg, not bind - null.

thanks help.

try using httppostedfilebase controller input argument in httppost request combined editorfor file container inside form shown in example below:

controller

[httppost] [validateantiforgerytoken] public actionresult submitstory(addstoryviewmodel model, httppostedfilebase storyimg)  {      // other stuff       if (storyimg != null)      {          string filename = string.format("{0}.jpg", new guid());          storyimg.saveas(server.mappath("~/img/") + filename);          newstory.storyimage = filename;               }       // other code add story data db       return redirecttoaction("success", new { storyid = newstory.storyid }); } 

view

@model storywall.viewmodels.addstoryviewmodel  @using (html.beginform("submitstory", "add", formmethod.post, new { enctype = "multipart/form-data" })) {     @html.antiforgerytoken()      <!-- other stuff -->      <div class="form-group">        <label class="control-label col-sm-2">add picture (optional)</label>        <div class="col-sm-10">        @html.editorfor(model => model.storyimage, new { htmlattributes = new { @class = "form-control", @type="file" }})        </div>     </div>      <!-- other stuff --> } 

if uploaded file still not available in storyimg, try using request.files retrieve file names post request:

foreach (string name in request.files) {     storyimg = this.request.files[name]; } 

nb: httppostedfile sealed class treated differently compared abstract class httppostedfilebase, property , method names inside them have similar.


Comments