带有ViewModel的ASP.NET MVC5控制器CRUD(2个模型)

时间:2016-05-24 04:01:25

标签: c# asp.net asp.net-mvc-5

在我的控制器中,我有一个包含2个不同模型的ViewModel,名为Drug and Food。

public class FoodDrugViewModel {
        public IEnumerable<SGHealthDesktop.Models.Drug> Drugs { get; set; }
        public IEnumerable<SGHealthDesktop.Models.Food> Foods { get; set; }

    }

在我的MainController中,这就是我将ViewModel传递给索引的方式。

 // GET: Admin
        public ActionResult Index() {
            FoodDrugViewModel vm = new FoodDrugViewModel(); //initialize it
            vm.Drugs = db.Drugs.ToList();
            vm.Foods = db.Foods.ToList();
            return View(vm);
        }

在我看来,我创建了两个表,并循环了每个模型中的项目,如下所示。

<table class="table" id="drugTable">
    <thead>
        <tr>
            <th>Drug Name</th>
            <th>Dosage</th>
            <th>Unit</th>
            <th>Type</th>
        </tr>
    </thead>
    @foreach (var item in Model.Drugs) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.DrugName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Dosage)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Unit)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Type)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.DrugId }) |
                @Html.ActionLink("Details", "Details", new { id = item.DrugId }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.DrugId })
            </td>
        </tr>
    }
</table>

 @foreach (var item in Model.Foods) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FoodName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Protein)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Carbohydrate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TotalFat)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.FoodId }) |
            @Html.ActionLink("Details", "Details", new { id = item.FoodId }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.FoodId })
        </td>
    </tr>
}

为了防止两个表同时出现,我使用了一个伴随JQuery的下拉列表,因此用户可以选择要查看的表,并且它按预期工作。 但是,我的问题如下

当我点击&#34;详情&#34; ActionLink,或者3个ActionLinks(详细信息,编辑,删除)中的任意一个,我希望显示相关信息。例如,如果我查看药物表,如果我点击&#34;详细信息&#34;,详细信息视图将显示药物信息,而食物信息也相同。

但是,我似乎无法弄清楚如何实现这一目标。我的详细方法如下,以药物为主要模型。如何检测用户是否选择查看Drug OR Food的详细信息?正如您在代码中看到的,它会立即根据ID找到药物详细信息。

// GET: Admin/Details/5
        public ActionResult Details(int? id) {
            if (id == null) {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Drug drug = db.Drugs.Find(id);
            if (drug == null) {
                return HttpNotFound();
            }
            return View(drug);
        }

至于Create,它没有任何问题,因为我可以再次允许下拉列表,以便用户可以选择他们想要创建的类型,药物或食物,并且将分别显示表单(假设在视图中)我使用的是FoodDrugViewModel而不是Drug模型。但是如何绑定控制器中的数据呢?默认情况下,Create方法如下所示。

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "DrugId,DrugName,Dosage,Unit,Type")] Drug drug) {
            if (ModelState.IsValid) {
                db.Drugs.Add(drug);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(drug);
        }

任何提供的帮助将不胜感激。提前谢谢!

更新:关于Create()的问题

在Create视图中,我将FoodDrugViewModel声明为

  

@model SGHealthDesktop.ViewModels.FoodDrugViewModel

我的药物表格看起来像这样(同样适用于食物)。

<div id="drugDiv">
            <div class="form-group">
                @Html.LabelFor(model => model.Drug.DrugName, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Drug.DrugName, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Drug.DrugName, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Drug.Dosage, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Drug.Dosage, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Drug.Dosage, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Drug.Unit, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Drug.Unit, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Drug.Unit, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Drug.Type, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownListFor(model => model.Drug.Type,
                     new SelectList(new[]
                    { "Diabetic Medication", "Hypertension", "Kidney Disease", "Insulin", "High Cholesterol"
                    }) as SelectList, new { @class = "btn btn-default dropdown-toggle form-control" })

                    @Html.ValidationMessageFor(model => model.Drug.Type, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>

我的Create()方法如下

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "DrugName,Dosage,Unit,Type")] FoodDrugViewModel vm) {
            try {
                if (ModelState.IsValid) {
                    if (vm.Drug != null) {
                        db.Drugs.Add(vm.Drug);
                    } 
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
            } catch (DataException dex) {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                System.Diagnostics.Debug.WriteLine(dex);
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }
            return View(vm.Drug);
        }

我在调用方法的行上放置了一个断点,&#34; Drug&#34;一片空白。我可以知道哪里出错了吗? :(

2 个答案:

答案 0 :(得分:2)

您可以再向ActionResult传递一个参数,以区分DrugFood。举个例子,我会添加type param,其值为drugfood

<强>药物

@foreach (var item in Model.Drugs) {
<tr>
  <td>
    @Html.DisplayFor(modelItem => item.DrugName)
  </td>
  <td>
    @Html.DisplayFor(modelItem => item.Dosage)
  </td>
  <td>
    @Html.DisplayFor(modelItem => item.Unit)
  </td>
  <td>
    @Html.DisplayFor(modelItem => item.Type)
  </td>
  <td>
    @Html.ActionLink("Edit", "Edit", new { id = item.DrugId, type="drug" }) | @Html.ActionLink("Details", "Details", new { id = item.DrugId, type="drug" }) | @Html.ActionLink("Delete", "Delete", new { id = item.DrugId, type="drug" })
  </td>
</tr>
} 

<强>食品

@foreach (var item in Model.Foods) {
<tr>
  <td>
    @Html.DisplayFor(modelItem => item.FoodName)
  </td>
  <td>
    @Html.DisplayFor(modelItem => item.Protein)
  </td>
  <td>
    @Html.DisplayFor(modelItem => item.Carbohydrate)
  </td>
  <td>
    @Html.DisplayFor(modelItem => item.TotalFat)
  </td>
  <td>
    @Html.ActionLink("Edit", "Edit", new { id = item.FoodId, type="food" }) | @Html.ActionLink("Details", "Details", new { id = item.FoodId, type="food" }) | @Html.ActionLink("Delete", "Delete", new { id = item.FoodId, type="food" })
  </td>
</tr>
}

您的ActionResult Details现在应该接受两个参数idtype

// GET: Admin/Details/5
public ActionResult Details(int? id, string type) {
  //You do not want to do anything if you don't have type value too, so the condition
  if (id == null || string.IsNullOrEmpty(type)) {
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
  }
  if(type=="drug"){
      Drug drug = db.Drugs.Find(id);
      if (drug == null) {
         return HttpNotFound();
      }
      return View(drug);
  }
  else
  {
      Food food = db.Foods.Find(id);
      if (food == null) {
         return HttpNotFound();
      }
      return View(food);
  }
}

希望您通过不同的models处理您的观点有效

修改

您也可以通过添加三元操作以下方式检查它,但不确定它是否可行。你可以尝试一下。

// GET: Admin/Details/5
public ActionResult Details(int? id, string type) {
  //You do not want to do anything if you don't have type value too, so the condition
  if (id == null || string.IsNullOrEmpty(type)) {
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
  }
  var model=type=="drug"?db.Drugs.Find(id):db.Foods.Find('id');
  if (model == null) {
      return HttpNotFound();
  }
  return View(model);
}

答案 1 :(得分:1)

我可以建议你两种方法来做到这一点。

  1. 对于药物和食物,创造6种不同的行为,如
  2.   

    Food_Edit,Food_Details,Food_Delete,Drug_Edit,Drug_Details,   Drug_Delete

    1. 传递指示类型的操作的另一个参数。在这种情况下,您可能需要另一种路由方法。
    2.   

      @ Html.ActionLink(“编辑”,“编辑”,新{id = item.FoodId,type =“Food”   })

           

      @ Html.ActionLink(“编辑”,“编辑”,新{id = item.DrugId,type =“Drug”   })