MVC 4编辑控制器/查看多对多关系和复选框 [英] MVC 4 Edit Controller/ View Many to Many relation and checkboxes

查看:196
本文介绍了MVC 4编辑控制器/查看多对多关系和复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET MVC 4和Entity Framework,我正在寻找一些方法来使我的db创建/编辑控制器和视图,使许多关系和复选框,我找到了答案与@ Slauma在 MVC 4 - 多对多关系和复选框中创建答案,但我真的想看看这个扩展到编辑和删除功能,以及像这个解决方案中的其他合作伙伴。有人可以请显示我如何填充ClassificationSelectViewModel在编辑控制器方法,以获得已选中和未选中值?这是一个马特花问题,这将解决我的太。

I'm working with ASP.NET MVC 4 and Entity Framework and I was searching for some way to make many to many relation and checkboxes from my db for a Create/Edit controller and view, I have found the answer with @Slauma answer for Create in MVC 4 - Many-to-Many relation and checkboxes but, I'd really like to see how this extends to Edit and Delete functionality as well like some other partners in this solution. Could someone please show how I would populate the ClassificationSelectViewModel in the Edit controller method to get both the "checked" and "unchecked" values? this is a Matt Flowers question that will solve mine too.

推荐答案

以下是此答案描述了对于具有多对多关系的模型的创建 GET和POST操作 公司。 >动作我将如何做(除了我可能不会把所有的EF代码到控制器动作,但提取它到扩展和服务方法):

The following is a continuation of this answer that describes Create GET and POST actions for a model with many-to-many relationship between entities Subscription and Company. Here is the procedure for the Edit actions how I would do it (except that I probably wouldn't put all the EF code into the controller actions but extract it into extension and service methods):

CompanySelectViewModel 保持不变:

public class CompanySelectViewModel
{
    public int CompanyId { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

SubscriptionEditViewModel SubscriptionCreateViewModel 加上订阅的键属性:

public class SubscriptionEditViewModel
{
    public int Id { get; set; }
    public int Amount { get; set; }
    public IEnumerable<CompanySelectViewModel> Companies { get; set; }
}

GET 动作可能如下所示:

public ActionResult Edit(int id)
{
    // Load the subscription with the requested id from the DB
    // together with its current related companies (only their Ids)
    var data = _context.Subscriptions
        .Where(s => s.SubscriptionId == id)
        .Select(s => new
        {
            ViewModel = new SubscriptionEditViewModel
            {
                Id = s.SubscriptionId
                Amount = s.Amount
            },
            CompanyIds = s.Companies.Select(c => c.CompanyId)
        })
        .SingleOrDefault();

    if (data == null)
        return HttpNotFound();

    // Load all companies from the DB
    data.ViewModel.Companies = _context.Companies
        .Select(c => new CompanySelectViewModel
        {
            CompanyId = c.CompanyId,
            Name = c.Name
        })
        .ToList();

    // Set IsSelected flag: true (= checkbox checked) if the company
    // is already related with the subscription; false, if not
    foreach (var c in data.ViewModel.Companies)
        c.IsSelected = data.CompanyIds.Contains(c.CompanyId);

    return View(data.ViewModel);
}

编辑创建视图以及订阅的键属性的隐藏字段 Id

The Edit view is the Create view plus a hidden field for the Subscription's key property Id:

@model SubscriptionEditViewModel

@using (Html.BeginForm()) {

    @Html.HiddenFor(model => model.Id)
    @Html.EditorFor(model => model.Amount)

    @Html.EditorFor(model => model.Companies)

    <input type="submit" value="Save changes" />
    @Html.ActionLink("Cancel", "Index")
}

用于选择公司的编辑器模板保持不变:

The editor template to select a company remains unchanged:

@model CompanySelectViewModel

@Html.HiddenFor(model => model.CompanyId)
@Html.HiddenFor(model => model.Name)

@Html.LabelFor(model => model.IsSelected, Model.Name)
@Html.EditorFor(model => model.IsSelected)

动作可能是这样的:

[HttpPost]
public ActionResult Edit(SubscriptionEditViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        var subscription = _context.Subscriptions.Include(s => s.Companies)
            .SingleOrDefault(s => s.SubscriptionId == viewModel.Id);

        if (subscription != null)
        {
            // Update scalar properties like "Amount"
            subscription.Amount = viewModel.Amount;
            // or more generic for multiple scalar properties
            // _context.Entry(subscription).CurrentValues.SetValues(viewModel);
            // But this will work only if you use the same key property name
            // in ViewModel and entity

            foreach (var company in viewModel.Companies)
            {
                if (company.IsSelected)
                {
                    if (!subscription.Companies.Any(
                        c => c.CompanyId == company.CompanyId))
                    {
                        // if company is selected but not yet
                        // related in DB, add relationship
                        var addedCompany = new Company
                            { CompanyId = company.CompanyId };
                        _context.Companies.Attach(addedCompany);
                        subscription.Companies.Add(addedCompany);
                    }
                }
                else
                {
                    var removedCompany = subscription.Companies
                       .SingleOrDefault(c => c.CompanyId == company.CompanyId);
                    if (removedCompany != null)
                        // if company is not selected but currently
                        // related in DB, remove relationship
                        subscription.Companies.Remove(removedCompany);
                }
            }

            _context.SaveChanges();
        }

        return RedirectToAction("Index");
    }

    return View(viewModel);
}

删除不难。在 GET 操作中,您可以加载一些订阅属性以显示在删除确认视图上:

The Delete actions are less difficult. In the GET action you could load a few subscription properties to display on the delete confirmation view:

public ActionResult Delete(int id)
{
    // Load subscription with given id from DB
    // and populate a `SubscriptionDeleteViewModel`.
    // It does not need to contain the related companies

    return View(viewModel);
}

POST 动作加载实体,然后删除它。没有必要包括公司,因为在多对多关系(通常)中,链接表上的级联删除被启用,使得数据库将关心与父一起删除链接条目,订阅

And in the POST action you load the entity and delete it then. There is no need to include the companies because in a many-to-many relationship (usually) cascading delete on the link table is enabled so that the database will take care of deleting the link entries together with the parent Subscription:

[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirm(int id)
{
    var subscription = _context.Subscriptions.Find(id);
    if (subscription != null)
        _context.Subscriptions.Remove(subscription);

    return RedirectToAction("Index");
}

这篇关于MVC 4编辑控制器/查看多对多关系和复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆