2016-12-05 11 views
0

ここの初心者です。 /イベント/詳細/ 3をリクエストするとエラーThe resource cannot be found.が表示されます。 私はMVVMを使用しています。ASP.Net MVC5 - "リソースが見つかりません"というエラー

スキーマは単純です。私は "イベント"、 "人"と "PersonInEvent"テーブルがあります。 "PersonInEvent"は、他の2つ(外部キーを保持する)のジャンクションテーブルです。

「詳細」ビューに、そのID(/イベント/詳細/ 3)のイベントのデータを表示しようとしています。イベントのIDは「詳細」コントローラアクションに渡され、イベントオブジェクトを保持するViewModelをインスタンス化します。このイベントは、ビューモデルが作成されたときに受け取るidを持つイベントに設定されます。

私のコントローラ(下記参照)によると、vm.Event == nullというエラーが表示されます。しかし、私はこの問題を解決する方法を見つけることができません。私はそれが私のビューモデル内の私の "イベント"プロパティがどのように作成されるかといった基本的なプログラミング問題であると感じています。しかし、私はまだ解決策を理解することはできません。前もって感謝します。

私のコントローラの詳細アクション:

[HttpPost] // this was the problem 
[ValidateAntiForgeryToken] 
public ActionResult Details(int id) 
    { 
     var vm = new EventDetailsViewModel(id); 

     if (vm.Event == null) 
     { 
      return HttpNotFound(); // I get the error because of this imo 
     } 

     return View("Details", vm); 
    } 

マイビューモデル:念のため

public class EventDetailsViewModel 
    { 
     private readonly ApplicationDbContext _db = new ApplicationDbContext(); 

     private readonly int _eventIdVm; 
     private Event _event; 

     public EventDetailsViewModel(int id) 
     { 
      _eventIdVm = id; 
      _event.EventId = id; 
     } 

     public Event Event 
     { 
      get 
      { 
       return _event = _db.Event.Find(_eventIdVm); 
      } 

      set { _event = value; } 
     } 

     public List<Person> Persons 
     { 
      get 
      { 
       if (!_db.PersonInEvent.Any(pe => pe.EventId == _eventIdVm)) 
       { 
        return Enumerable.Empty<Person>().ToList(); 
       } 
       var personsOfEvent = _db.PersonInEvent.Where(pe => pe.EventId == _eventIdVm) 
        .Select(pe => pe.Person) 
        .ToList(); 
       return personsOfEvent; 
      } 
     } 
    } 

マイビュー:

@model BillSplittingWebApp.ViewModels.EventDetailsViewModel 

@{ 
    ViewBag.Title = "Details"; 
} 

<h2>Details</h2> 

<div> 
    <h4>Event</h4> 
    <hr /> 
    <dl class="dl-horizontal"> 
     <dt> 
      @Html.DisplayNameFor(model => model.Event.EventName) 
     </dt> 

     <dd> 
      @Html.DisplayFor(model => model.Event.EventName) 
     </dd> 

     <dt> 
      @Html.DisplayNameFor(model => model.Event.EvenTimeBegin) 
     </dt> 

     <dd> 
      @Html.DisplayFor(model => model.Event.EvenTimeBegin) 
     </dd> 

    </dl> 
</div> 

EDIT:問題だった属性[HttpPost]こと私はactiのために削除するのを忘れましたに。

+2

をフォームがポストされたときにのみ、[HttpPost]理由属性を、呼び出される上記 'Details'方法。属性[HttpGet]を使用する 'Details'メソッドもありますか?もしそうなら、そのコードもあなたの質問に含めてください。 –

+0

@Peter Bそれは確かにそれでした...私はidメソッドを以前に送信しようとしましたが、属性を削除するのを忘れました。 –

+1

サイドノート、これはMVVMではなく、MVCです。それがaspnet * MVC *と呼ばれる理由です。 – Will

答えて

3

これはMVCが貧弱な方法です。それは自分自身のパターンです。 ViewModelはデータベースを直接参照するべきではありません。しかし、あなたのviewModelではprivateイベントオブジェクトが宣言されています。コンストラクタでは、最初に新しいインスタンスをインスタンス化せずにこのオブジェクトのIDを設定しようとしています。

それはとにかく、コンストラクタに有用何もしていないとして、あなたはこのコード行を削除することができます

_event.EventId = id; 
+0

ありがとうbilpor。問題は私の_HttpPost_属性でした。あなたが言及した行は、私が一度それを削除すると消えてしまうエラーを投げた。 "_ViewModelsはデータベースを直接参照してはいけません"というように、コントローラのビューモデルのプロパティを設定し、そのコントローラのロジックを構築する必要があります。 –

+1

はい、MVCのポイントはModel-View-Controllerの名前です。コントローラはできるだけ軽くなければなりません。これを調べる最良の方法は、データをサービスレイヤーとデータレイヤーに渡すスイッチングメカニズムです。 viewModelsは、ビューが表示する必要のあるデータを定義する必要があります。ここではコンストラクタを持つのは良いことですが、コントローラから割り当てられます。 (懸念の分離を参照)、固体原則とDRY。これらを念頭に置いて常にコーディングしてください。間違ったことはありません。また、「守備的な」コーディングも検討してください。それが壊れてしまうと誰かがそれを壊すでしょう。 – bilpor

関連する問題