2017-04-05 9 views
1

私はデータベースのフォームからデータを格納するWebアプリケーションを構築しています。私の最初のアプローチは、カスタムモデル/クラスを作成し、それにPOSTデータをバインドすることでした。これは私が首尾よく使用していたアプローチでした。しかし、今回は単純に機能しませんでした。私がしても、オブジェクトのプロパティ(例:model.Title)に値をバインドすることはできませんでしたが、プリミティブ値(String title)だけです。フラストレーションの中で、私はついに、データをプリミティブにバインドすることに決めました。Asp.net MVC - モデルバインディングのみプリミティブ値を使用して

しかし、データの大部分は正しくバインドされていますが、データがHttpPostedFileBaseオブジェクトにバインドされていないという別の問題がありました。最初は、自分のカスタムクラスに何か問題があった可能性があると仮定していました。モデルバインダーは、オブジェクト(プリミティブのみ)に正しくバインドすることができなくなりました。

マイビュー上記のビューを生成し、POSTデータを受け入れる責任

@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 is 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 is 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 a store.</span></div></div> 

    <div class="form-group"><label class="control-label col-sm-2">Add a 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 your 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 your email.</span></div></div> 


    <div ng-controller="TagsCtrl" class="form-group"> 
     <label class="control-label col-sm-2">Tags (separate with a 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> 

[コントローラ:

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) { 
       for (int i = 0; i < 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); 

    } 
} 

}

のみ非プリミティブ、StoryImg、結合しません - 常にnullです。

ありがとうございました。

答えて

1

以下の例に示すように、フォーム内のファイルコンテナとしてEditorFor組み合わせるHttpPost要求にコントローラ入力引数としてHttpPostedFileBaseを使用してみてください:

コントローラ

[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 to add story data into DB 

    return RedirectToAction("Success", new { storyID = newStory.StoryID }); 
} 

表示

@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 a 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 --> 
} 

StoryImgではまだ利用できませんアップロードされたファイルの場合、POST要求からファイル名を取得するためにRequest.Filesを使用してみてください:

foreach (String name in Request.Files) 
{ 
    StoryImg = this.Request.Files[name]; 
} 

NB:HttpPostedFileabstractクラスHttpPostedFileBase、でもプロパティと比較して異なって扱わsealedクラスであり、それらのメソッド名はやや似ています。

+0

詳細な説明とコードをお寄せいただきありがとうございます! – KellyMarchewa

1

HttpPostedFileの代わりにHttpPostedFileBaseを使用しようとしましたか?

+0

なぜこれが答えを解決するのか説明し、その使い方の例を挙げてください。 – Adam

+0

ありがとうございました!私は今、かなりばかげていると感じます。これが全体の問題でした。実際にクラスを切り替えるだけで、私が使ったアプローチでしたが、より詳細な回答を受け入れられるようにするのが適切かもしれないと思います。 – KellyMarchewa

関連する問題