ado.net mvc3 кортеж, использующий в модели и одиночные представления - PullRequest
6 голосов
/ 14 ноября 2011

У меня есть следующая модель ADO

Студент Id, Имя и Курс Id, Имя, Student_ID

Я сделал следующее представление для него

@model Tuple<MvcApplication4.Models.Course, MvcApplication4.Models.Student >
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Course</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Item1.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Item1.Name)
            @Html.ValidationMessageFor(model => model.Item1.Name)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Item1.S_ID, "Student")
        </div>
            <fieldset>
        <legend>Student</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Item2.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Item2.Name)
            @Html.ValidationMessageFor(model => model.Item2.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Item2.Class)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Item2.Class)
            @Html.ValidationMessageFor(model => model.Item2.Class)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

    </fieldset>
}

И контроллер для него выглядит как

public ActionResult Create()
{
      return View();
} 

//
// POST: /Default3/Create

[HttpPost]
public ActionResult Create(Tuple<Student ,Course > t)
{

    try
    {
        // TODO: Add insert logic here

        db.Students.AddObject(t.Item1);
        db.SaveChanges();

        t.Item2.S_ID = t.Item1.Id;
        db.Courses.AddObject(t.Item2);
        db.SaveChanges();

        return RedirectToAction("Copy");
    }
    catch
    {
        return View();
    }
}

Но когда я нажимаю кнопку Creat, этовыдает следующую ошибку

Ошибка сервера в приложении '/'.

Для этого объекта не определен конструктор без параметров.

Ответы [ 6 ]

11 голосов
/ 14 ноября 2011

Класс Tuple<X, Y> не имеет конструктора по умолчанию, поэтому вам нужно написать собственный механизм связывания модели, если вы хотите, чтобы это работало.Другая возможность состоит в использовании пользовательской модели представления, которую я бы порекомендовал вам:

public class MyViewModel
{
    public Course Course { get; set; }
    public Student Student { get; set; }
}

, а затем:

public ActionResult Create()
{
    return View(new MyViewModel());
} 

//
// POST: /Default3/Create

[HttpPost]
public ActionResult Create(MyViewModel model)
{
    try
    {
        // TODO: Add insert logic here
        db.Students.AddObject(t.Student);
        db.SaveChanges();

        t.Course.S_ID = t.Student.Id;
        db.Courses.AddObject(t.Course);
        db.SaveChanges();

        return RedirectToAction("Copy");
    }
    catch
    {
        return View(model);
    }
}

и, наконец,

@model MvcApplication4.Models.MyViewModel
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Course</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Student.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Student.Name)
            @Html.ValidationMessageFor(model => model.Student.Name)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Student.S_ID, "Student")
        </div>
            <fieldset>
        <legend>Student</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Course.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Course.Name)
            @Html.ValidationMessageFor(model => model.Course.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Course.Class)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Course.Class)
            @Html.ValidationMessageFor(model => model.Course.Class)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
2 голосов
/ 14 ноября 2011

Вам необходимо передать модель на ваше усмотрение. Пример:

return View(model);
2 голосов
/ 14 ноября 2011

MVC довольно умен, но он не может понять, как создать новый экземпляр Tuple и создать новые экземпляры элементов, а затем назначить ему соответствующие элементы. Это слишком сложная задача.

Ошибка, которую вы получаете, состоит в том, что кортеж не имеет конструктора по умолчанию без параметров и требует, чтобы ему были переданы новые элементы в конструкторе, чего не может сделать MVC.

Вам придется разбить это и создать свой кортеж в действии контроллера из модели представления, которая содержит ваши элементы в качестве участников.

1 голос
/ 24 апреля 2013

Это, похоже, решило проблему для меня как альтернативы, и теперь она работает:

[HttpGet]
public ActionResult Create()
{  
    Course course = new Course();
    Student student = new Student();
    var tuple = new Tuple<Course,Student>(course,student);
    return View(tuple);
}

[HttpPost]
public ActionResult Create(Tuple<Course,Student> tuple){ do something ...}

Я пробовал несколько других подходов, включая те, которые были предложены здесь, но не решили проблему. Я только что опубликовал это, чтобы помочь кому-то еще, кто захочет использовать Tuple, используйте его, только если у вас нет другой альтернативы.

0 голосов
/ 04 августа 2016

Вы должны связать префикс в параметрах Контроллер:

public ActionResult ThisMethod([Bind(Prefix = "Item1")] AccountViewModel model)
{
            // toDo
}

Вид:

@model Tuple<AccountViewModel>

@Html.EditorFor(model => model.Item1.Firstname)  
0 голосов
/ 12 декабря 2013

Я получил его на работу после нескольких минут копания и размышлений.Вот краткий пример того, что я сделал:

GET action:

[HttpGet]        
public ActionResult Update(int id = 0) 
{
    ProductDto product = _productService.FindByID(id);
    SupplierDto supplier = _supplierService.FindByProductID(productId: product.ProductID);        

    return View(model: new Tuple<ProductDto, SupplierDto>(product, supplier));
}

POST action:

[HttpPost]
public JsonResult Update(int id = 0, ProductDto Item1, SupplierDto Item2) 
{
    // Get the product name
    string productName = Item1.ProductName;

    // Get the supplier name
    string supplierName = Item2.SupplierName;

    ...

    return Json(new { success = true });
}

Просмотр:

@model Tuple<ProductDto, SupplierDto>
@{
    ViewBag.Title = "add title later ... ";
    AjaxOptions options = new AjaxOptions { ... };
}

@using (Ajax.BeginForm("Update", "Product", options, htmlAttributes: new { @id = "update-form" })) 
{
    <fieldset>
        <legend>Update Product</legend>
        <div class="display-label">
            @Html.LabelFor(model => model.Item1.ProductName)         
        </div>
        <div class="display-field">
            @Html.EditorFor(model => model.Item1.ProductName)            
        </div>

        ...

         <div class="display-label">
            @Html.LabelFor(model => model.Item2.SupplierName)
        </div>
        <div class="display-field">
            @Html.EditorFor(model => model.Item2.SupplierName)            
        </div>
    </fieldset>
    <div class="submit-button">
        <button type="submit" class="button">Update details</button>
    <div>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...