A dynamic field for each database record

Asked

Viewed 478 times

3

I have a property called Productdevelopment where I have several functions and must assign a user to each function. I have an Editortemplate to return a list of users. I have to create a dynamic field for each function registered in the database and each field will use Editortemplate to list users. (as in the image below). I created a heavily typed Editortemplate (Functionsusuarios.cshtml) (@model ICollection<FuncaoUsuario>), that generates the fields, as in the image below, but I do not know what to do to return the values to the Model. I thought about using a hidden multiselect, but I’m finding it very complicated.

inserir a descrição da imagem aqui

My class

public class FuncaoUsuario //Não mapeado
{
    public int IdFuncao { get; set; }
    public string Usuario { get; set; }
    public string DscFuncao { get; set; }
}

My field in View (Productdevelopment property)

public ICollection<FuncaoUsuario> ProductDevelopment { get; set; }

My Editortemplate -> Functionsusuarios.cshtml

@model ICollection<FuncaoUsuario>
@{
    var modelMetaData = this.ViewData.ModelMetadata;
    var propertyName = modelMetaData.PropertyName;    
}




@foreach (FuncaoUsuario item in this.Model)
{
    var id = "id" + Guid.NewGuid().ToString().Substring(0, 5);    
    List<SelectListItem> listValues = new List<SelectListItem>();
    if (!string.IsNullOrEmpty(item.Usuario))
    {
        listValues.Add(new SelectListItem { Selected = true, Text = item.Usuario, Value = item.Usuario });
    }     
    <div id="@id" class="field-middle">
        <h3>@String.Format(Html.LabelFor(model => model).ToString(), item.DscFuncao) :</h3>
        @Html.DropDownList("", listValues, new { id = "PD" + item.IdFuncao.ToString() })
    </div>
    <script language="javascript" type="text/javascript">
        $("#@id select")
            .turnAutoComplete("@Url.Action("UsersListJson", "Security")");
    </script> 
}


<select name="@propertyName" multiple="multiple" size=30 style='height: 100%;' >
@foreach (FuncaoUsuario item in this.Model)
{   
<option value="@item.IdFuncao">teste</option>
}
</select>

[EDITED]

I made the changes as below using Begincollectionitem

Models:

public partial class Modelo
{
    public ICollection<FuncaoUsuario> ProductDevelopment { get; set; }
    //Continua...
}
public class FuncaoUsuario 
{
    public int IdFuncao { get; set; }
    public string Usuario { get; set; }
    public string DscFuncao { get; set; }
}

Controller:

public ViewResultBase Editar(int id)
{
    Modelo model = this.Service.GetForEdit(this.IdEmpresa, id);
    return base.SwitchView(model);
}

View Principal:

 @model Modelo

    <div class="box-fields">
        @using (Ajax.BeginForm(
            this.DefaultActionEdit,
            "Modelo",
            new DefaultAjaxOptions()
        ))
        {      
@Html.EditorFor(i => i.ProductDevelopment) //precisa desta propriedade na view principal, pra nao dar o erro mencionado abaixo. E tem que remover o template Collection.cshtml.
            foreach (FuncaoUsuario userFunction in this.Model.ProductDevelopment)
            {
                Html.RenderPartial("_UsuarioFuncao", userFunction);
            }   

    //Mais coisas....
    }

Partial View:

@model FuncaoUsuario

@using (Html.BeginCollectionItem("ProductDevelopment")) 
{  

    List<SelectListItem> listValues = new List<SelectListItem>();
    if (!string.IsNullOrEmpty(this.Model.Usuario))
    {
        listValues.Add(new SelectListItem { Selected = true, Text = this.Model.Usuario, Value = this.Model.Usuario });
    }

    @Html.HiddenFor(x => x.IdFuncao)
    @Html.EditorFor(x => x.Usuario, "Usuario")    
}

Error found:

Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

Source Error: 


Line 1:  @model FuncaoUsuario
Line 2:  
Line 3:  @using (Html.BeginCollectionItem("ProductDevelopment")) <- erro nesta linha.
Line 4:  {  
  • 1

    look for Begincollectionitem, is a helper Asp.net mvc for this type of situation

  • Returned to the Model or for the Controller?

  • Returned to Model (Typed Template Editor). Begincollectionitem seems to be what I’m looking for. Which namespace should I use, why I tried to do so using (Html.BeginCollectionItem("FuncaoUsuario")), but the helper did not recognize "Begincollectionitem"?

  • I put the image of how the view should look (I had forgotten).

  • I just found Nuget -> Install-Package Begincollectionitem (I’ll try to use it and see how it looks.)

1 answer

3


It is a classic case of the use of nuget pack BeginCollectionItem. It is not native to ASP.NET MVC or Razor. It needs to be installed.

I’ve answered several questions about. If necessary, please edit your question so I can make the appropriate additions in the answer.


EDIT

If there is this error:

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

It’s because Begincollectionitem inserts a EditorTemplate called Collection.cshtml which may give some problems. It is recommended to delete it to define your Partial.

The exact location of this Template gets into Views\Shared\EditorTemplates\Collection.cshtml.

  • I edited my question and put the modified code to use the Bible. The way it’s going wrong there (see at the end of the edited question).

  • @Elizeu What is the need for this? var id = "id" + Guid.NewGuid().ToString().Substring(0, 5);. The BeginCollectionItem already defines a temporary Id for you. You can define another identifier on Controller in time to save.

  • This "id" is garbage, I forgot to delete when I copied from another template. But it’s not the reason for the error I already took it.

  • he is not recognizing "Productdevelopment" as a Collection.

  • @Elizeu Or some userFunction is void. Make a Debug.

  • I did Debug and all items have value. O "BeginCollectionItem("ProductDevelopment")" is correct? I quote the property of my model?

  • @Elizeu Yes, that part is correct. As I recall, this mistake of index is something very silly, and that has to do with the collection itself. index is a field that the component places in the form to identify items in a collection.

  • 1

    I reinstalled the Begincollecionitem package and stopped giving error. Now ta entering a "Collection.cshtml" template that comes with the package. I have to use this view (Collection.cshtml) to assemble my fields?

  • @Elizeu Ah! That’s right. Remove this template that the problem should stop.

  • Now it works. There’s only one defect. I need the id to be in a Hiddenfor and it’s displaying the values. But the main one worked already.

  • @Elizeu This is simpler. Need help?

  • No, the worst is over. I’ve been at it since yesterday. The architect went on vacation and I had no one to turn to.

  • 1

    I figured it out. It wasn’t Hiddenfor, it was this -> @Html.EditorFor(i => i.ProductDevelopment), was displaying the ids. I switched to this @Html.Hiddenfor(i => i.Productdevelopment) and solved it. Thanks for the help.

Show 8 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.