1

We are using dynamic views to display and edit the records.

Say I have a model A:

public class A
{
    public int AID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int organizationid { get; set; }
}

And class B:

public class B
{
    public int organizationid { get; set; }
    public string orgnmae { get; set; }
    public string orgdesc { get; set; }
}

here organizationid of table B is foreign key in table A.

Now I have dynamic editor view,

@model dynamic
@using (Html.BeginForm("Edit", null,  FormMethod.Post))
 {
   @Html.EditorForModel()

 <input type="submit" value="Edit" />
}

If we choose to edit any A's record, it will display this editor view with all text boxes. But for organizationid I should not show integer value in it. Instead I should show a dropdown with available organizations of table B and user can choose one of them to edit.

How can I handle this? I read Darin's answers here; that's a good suggestion, but in my case the dropdown items should be part of another model.

halfer
  • 19,824
  • 17
  • 99
  • 186
mmssaann
  • 1,507
  • 6
  • 27
  • 55

3 Answers3

1

If I was tackling this problem in a way you are suggesting, then I would make a change to A. If you aren't going to use a viewmodel, then you will need to extend it's properties.

public class A
{

    [ScaffoldColumn(false)]
    public int OrganizationId { get; set; }


    [Display(Name="OrganizationId")]
    [UIHint("DropDownList")]
    public IEnumerable<SelectListItem> Organizations { get; set; }
}

You notice that I have overridden the name field of the Organizations so that the value is fed back into model binding as OrganizationId. When you build this model, you are going to have create the orgranizations property as a list or array of selectlistitems from the organisation instances that are relevant.

I have also set the original organizationid to not be scaffolded so hopefully that will stop it participating in the render process.

You will of course need to make the template DropDownList in your editortemplates.

HTH

Slicksim
  • 7,054
  • 28
  • 32
  • I guess I cannot have IEnumerable in my model class. because it requires system.web.mvc namespace and i cannot add this assembly in my BIz projects.. – mmssaann Jul 16 '13 at 09:04
  • ah, no big deal there, you can pass out any type in that list, you will just need to be able to convert it to a select list item is all – Slicksim Jul 16 '13 at 09:07
  • you will need to have a common type that your DropDownList template can bind into a dropdown list, then any entities that you want to be dropdowns will need to be convertible into this type, most likely by an implicit operator or an adapter pattern. you can take your pick on the method as to what suits you better – Slicksim Jul 16 '13 at 09:15
  • am afraid it will be a google and search job, you can look for things like implicit operator and converting lists etc. am afraid am at work so can't knock up a sample at the mo – Slicksim Jul 16 '13 at 09:28
  • no prob..thanks 4 guidance..i will take a look and update u :) – mmssaann Jul 16 '13 at 09:29
  • I followed the same, but it is failing in dropdown list editor template with "Cannot perform runtime binding on a null reference", code : @Html.DropDownListFor( x => 1, new SelectList(Model.Items, "Value", "Text", 1) ) – mmssaann Jul 16 '13 at 10:57
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33560/discussion-between-slicksim-and-mmssaann) – Slicksim Jul 16 '13 at 14:11
0

I'm not too sure if I understand your question correctly. I never use EditorFor, I just add the fields directly from the view model. It gives me more control. From what I can gather it seems like you want to edit class A and have class B in a drop down list?

This is how I will define class A and class B given the names of your properties, please excuse if I am mistaken. class A is class User and class B is class Organization. You need to give your properties better descriptions so that people can read them better.

public class User
{
     public int UserId { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public int OrganizationId { get; set; }
}

public class Organization
{
     public int OrganizationId { get; set; }

     public string OrganizationName { get; set; }

     public string OrganizationDescription { get; set; }
}

You need to have a view model to represent your data on your view.

public class EditUserViewModel
{
     public int UserId { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public int OrganizationId { get; set; }

     public IEnumerable<Organization> Organizations { get; set; }
}

public ActionResult Edit(int id)
{
     // Get the user by id
     User user = userRepository.GetById(id);

     // You can use a mapping tool here to map from domain model to view model.
     // I did it differently for the sake of simplicity

     EditAViewModel viewModel = new EditAViewModel
     {
          UserId = user.UserId,
          FirstName = user.FirstName,
          LastName = user.LastName,
          OrganizationId = user.OrganizationId,
          Organizations = organizationRepository.GetAll()
     };

     // Return the populated view model to the view    
     return View(viewModel);
}

[HttpPost]
public ActionResult Edit(EditAViewModel viewModel)
{
     if (!ModelState.IsValid)
     {
          viewModel.Organizations = organizationRepository.GetAll();

          return View(viewModel);
     }

     // If validation succeeds do what ever you have to do here, like edit in database
}

And this is how your view will look like.

@model YourProject.ViewModels.Users.EditUserViewModel

@using (Html.BeginForm())
{
     <table>
          <tr>
               <td class="edit-label">First Name:</td>
               <td>
                    @Html.TextBoxFor(x => x.FirstName)
                    @Html.ValidationMessageFor(x => x.FirstName)
               </td>
          </tr>
          <tr>
               <td class="edit-label">Last Name:</td>
               <td>
                    @Html.TextBoxFor(x => x.LastName)
                    @Html.ValidationMessageFor(x => x.LastName)
               </td>
          </tr>
          <tr>
               <td class="edit-label">Organization:</td>
               <td>
                    @Html.DropDownListFor(
                         x => x.OrganizationId,
                         new SelectList(Model.Organizations, "OrganizationId", "OrganizationName", Model.OrganizationId),
                         "-- Select --"
                    )
                    @Html.ValidationMessageFor(x => x.OrganizationId)
               </td>
          </tr>
     </table>

     <button id="SaveButton" type="submit">Save</button>
}

This is how I do it. You can modify the code to fit in with your scenario.

I hope this helps.

Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234
  • thanks for the detailed answer. But your view is strongly typed, in my it is dynamic view. see the view in my question. now me having a "EditUserViewModel" object, how can I show it on dynamic view with dropdown, can u shed some light? – mmssaann Jul 16 '13 at 07:02
  • What do you mean by dynamic view? Why do you need `@model dynamic`. `Views should be strongly typed`. – Brendan Vogt Jul 16 '13 at 07:27
  • 1
    As you know the views can be rendered in two ways 1)strongly typed 2)dynamic. I can pass any object to dynamic view (say User or department whatever) it should handled those objects. so we are using dynamic views. – mmssaann Jul 16 '13 at 07:30
0

Hi Try like this

Model

  public class CustomerModel
    {
        public int CustomerId { get; set; }

        public string customerName { get; set; }
}

View

@model dynamic
@{
    Layout = null;
}

 @Html.DropDownList("CustomerId", (SelectList) ViewBag.CustomerNameID,"--Select--")

Contrller

[HttpGet]
        public ActionResult CustomerInfo()
        {

            var List = GetCustomerName();
            ViewBag.CustomerNameID = new SelectList(List, "CustomerId", "customerName");
            return View();
        }
Jaimin
  • 7,964
  • 2
  • 25
  • 32