Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ado.net mvc3 tuple using in model and single views

I have the following ADO Model

Student Id,Name and Course Id,Name,Student_ID

I have made the following view for it

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

And the controller for it is as

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();
    }
}

But When i click the Creat button it gives the following Error

Server Error in '/' Application.

No parameterless constructor defined for this object.

like image 354
Muhammad Nauman Avatar asked Nov 14 '11 07:11

Muhammad Nauman


People also ask

Can we use 2 models in a view?

You can use multiple models in a single view by creating a common model for all the models that are to be used in a single view. To achieve this, refer to the following steps. First, create a new model (common for all models) and refer all other models that are to be used in the same view.

Can a controller have multiple views?

Yes You can use multiple View in one Controller.


4 Answers

The Tuple<X, Y> class doesn't have a default constructor so you will need to write a custom model binder if you want this to work. Another possibility is to use a custom view model which is what I would recommend you:

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

and then:

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);
    }
}

and finally:

@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>
}
like image 97
Darin Dimitrov Avatar answered Nov 15 '22 08:11

Darin Dimitrov


MVC is pretty smart, but it can't really figure out how to create a new instance of Tuple and create new instances of the items, then assign the proper items to it. That's just too complex of a task.

The error you get is because a Tuple doesn't have a default parameterless constructor, and requires new items to be passed to it in the constructor, something that MVC can't do.

You will have to break this down, and create your tuple in your controller action from a viewmodel that contains your items as members.

like image 42
Erik Funkenbusch Avatar answered Nov 15 '22 08:11

Erik Funkenbusch


You need to pass the model to your view. Example:

return View(model);
like image 27
dip Avatar answered Nov 15 '22 09:11

dip


This seems to have resolved the issue for me as an alternative and it is working now:

[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 ...}

I tried several other approaches include some that have been suggested here but, didn't resolve the problem. I just posted this to help someone else who might want to use Tuple though, use it only if you don't have another alternative.

like image 28
FrankDev Avatar answered Nov 15 '22 09:11

FrankDev