ASP MVC HTML 表单 POST List

发布于 2024-10-07 03:02:31 字数 5700 浏览 0 评论 0原文

今天我一整天都在为同样的问题而苦苦挣扎。我仍然是 ASP MVC 初学者,来自 Flex 世界。但现在我正在从事一些 ASP MVC 项目。

我认为这是一个相当复杂的问题,因此我试图非常详细地描述这个问题。所以提前感谢您,您正在讨论这个问题!

系统描述:

我正在尝试构建一个“项目管理系统”。您可以拥有多个项目,其中每个项目都有一个名称和描述。项目还列出了其他详细信息。正常的表单可以让我输入新项目的名称和描述,对吗?

现在,要求是可以添加额外的表单元素。例如,我想添加一个新的输入,让我输入所有现有项目和新项目的可用预算。

预算是额外的项目细节。 IE。添加预算的 a from 元素后,新的项目详细信息将添加到所有项目中。

类:

我得到了“Project”类,它有一个“ProjectDetails”列表,它还提供了一些接口来从“Project”中获取、添加和删除“ProjectDetail”

public class Project : ProjectItem
{
    public virtual IList<ProjectDetail> Details { get; set; }

    public Project(string name, string description) : base(name, description)
    {
        Details = new List<ProjectDetail>();
    }

    public Project()
        : this("new project", "this is a new project")
    { 

    }

    public virtual void AddDetail(string name)
    {
        var detail = GetDetail(name);

        if (detail == null)
        {
            detail = new ProjectDetail(name, "empty");
            detail.Project = this;
            Details.Add(detail);
        }
    }

    public virtual void RemoveDetail(string name)
    {
        var detail = GetDetail(name);

        if (detail != null)
        {
            detail.Project = null;
            Details.Remove(detail);
        }
    }

    public virtual ProjectDetail GetDetail(string name)
    {
        ProjectDetail result = null;

        foreach (ProjectDetail detail in Details)
        {
            if (detail.Name.Equals(name))
            {
                result = detail;
            }
        }

        return result;
    }
}

:类如下所示:

public class ProjectDetail : ProjectItemDetail
{
    [NotNull]
    public virtual Project Project { get; set; }

    public ProjectDetail(string name, string value)
        : base(name, value)
    { 

    }

    public ProjectDetail()
        : this("new project detail", "empty")
    { 

    }
}

请注意,“ProjectDetail”从“ProjectItem”基类继承名称和值。

我正在尝试创建视图,这将允许我编辑特定“项目”的详细信息列表中所有“项目详细信息”的单个值属性。 现在,每个“ProjectDetail”都与一个“FormElement”相关,并且它们通过其 Name 属性进行匹配。

public class FormElement
{
    public static string TYPE_UNKNOWN   = "typeUnknown";
    public static string TYPE_NUMERIC   = "typeNumeric";
    public static string TYPE_CHAR      = "typeChar";
    public static string TYPE_DATE      = "typeDate";

    [NotNull]
    public virtual string Name { get; set; }

    [NotNull]
    public virtual int Position { get; set; }

    [NotNull]
    public virtual string Type { get; set; }

    [NotNull]
    public virtual Form Form { get; set; }

    public FormElement(string name, int position, string type)
    {
        Name = name;
        Position = position;
        Type = type;
    }

    public FormElement()
        : this("unknownFormElement", -1, TYPE_UNKNOWN)
    {

    }

}

和“Form”类:

public class Form : Entity
{
    [NotNull]
    public virtual string Name { get; set; }

    public virtual IList<FormElement> FormElements { get; set; }

    public Form(string name)
    {
        Name = name;

        FormElements = new List<FormElement>();
    }

    public Form()
        : this("unknownWebform")
    { 

    }

    //public interface for getting, adding, deleting FormElement 
}

因此,视图需要渲染“Form”并使用相关“ProjectDetail”的值填充元素。

因此,视图在“ProjectEditModel”中传递:

public class ProjectEditModel
{
    public Form Form;

    public Project Project;

    public ProjectViewModel() {}
}

以下视图被强类型化为“ProjectEditModel”:

<% using (Html.BeginForm("Edit", "Project", FormMethod.Post))
   {%>

        <div>
        <fieldset>
            <legend>Edit Project</legend>

            <div class="editor-label">
                <%: Html.LabelFor(m => m.Project.Name) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(m => m.Project.Name)%>
            </div>

            <div class="editor-label">
                <%: Html.LabelFor(m => m.Project.Description)%>
            </div>
             <div class="editor-field">
                <%: Html.TextBoxFor(m => m.Project.Description)%>
            </div>

            <% 

                foreach (var formElement in Model.Form.FormElements)
                {   
                    if (formElement.Type.Equals(Domain.Model.FormElement.TYPE_CHAR))
                    { 
                    %>
                        <div class="editor-label">
                            <%: Html.Label(Model.Project.GetDetail(formElement.Name).Name)%>
                        </div>
                        <div class="editor-field">
                            <%: Html.TextBoxFor(m => m.Project.GetDetail(formElement.Name).Value)%>
                        </div>
                    <%
                    }
                    if (formElement.Type.Equals(Domain.Model.FormElement.TYPE_NUMERIC))
                    {

                    }
                }

            %>

            <p>
                <input type="hidden" name="Id" value="<%: Model.Project.Id %>" />
                <input type="submit" value="Save" />
            </p>

        </fieldset>
    </div>

<% } %>

这将正确呈现并为每个附加细节显示一个表单元素。但是当我发回模型时,构造函数将被调用,这样我就丢失了所有引用。彭!

我读过,MVC “就是这样工作的”,我愿意接受这一点,但是我该如何解决我的问题呢?您需要更多信息吗?

非常感谢,非常感谢帮助!

Today I have been struggling with the same problem all day. I am still ASP MVC beginner, coming from the Flex world. But now I am working on some ASP MVC project.

I think this is a quite complex problem, therefore I am trying to describe the problem very detailed. So thank you in advance, that you are talking the time to go through this!

System description:

I am trying to build a "ProjectManagementSystem". You can have multiple projects, where each project has a name and a description. A project also has a list off additional details. A normal form would let me enter name and description for a new project, right?

Now, the requirement is, that additional form elements can be added. For example I want to add a new input which will let me enter the available budget for all existing and new projects.

The budget is an additional project detail. IE. when the a from element for the budget is added, a new project detail is added to all projects.

Classes:

I got the class "Project" which has a list of "ProjectDetails" and it also provides some interface to get, add and delete a "ProjectDetail" from the "Project":

public class Project : ProjectItem
{
    public virtual IList<ProjectDetail> Details { get; set; }

    public Project(string name, string description) : base(name, description)
    {
        Details = new List<ProjectDetail>();
    }

    public Project()
        : this("new project", "this is a new project")
    { 

    }

    public virtual void AddDetail(string name)
    {
        var detail = GetDetail(name);

        if (detail == null)
        {
            detail = new ProjectDetail(name, "empty");
            detail.Project = this;
            Details.Add(detail);
        }
    }

    public virtual void RemoveDetail(string name)
    {
        var detail = GetDetail(name);

        if (detail != null)
        {
            detail.Project = null;
            Details.Remove(detail);
        }
    }

    public virtual ProjectDetail GetDetail(string name)
    {
        ProjectDetail result = null;

        foreach (ProjectDetail detail in Details)
        {
            if (detail.Name.Equals(name))
            {
                result = detail;
            }
        }

        return result;
    }
}

The "ProjectDetail" class looks like this:

public class ProjectDetail : ProjectItemDetail
{
    [NotNull]
    public virtual Project Project { get; set; }

    public ProjectDetail(string name, string value)
        : base(name, value)
    { 

    }

    public ProjectDetail()
        : this("new project detail", "empty")
    { 

    }
}

Note, that "ProjectDetail" inherits Name and Value from "ProjectItem" base class.

I am trying to create view, that will let me edit the single Value property of all "ProjectDetails" in the Details list of a particular "Project".
Now, each "ProjectDetail" is related to a "FormElement" and they are matched by their Name property.

public class FormElement
{
    public static string TYPE_UNKNOWN   = "typeUnknown";
    public static string TYPE_NUMERIC   = "typeNumeric";
    public static string TYPE_CHAR      = "typeChar";
    public static string TYPE_DATE      = "typeDate";

    [NotNull]
    public virtual string Name { get; set; }

    [NotNull]
    public virtual int Position { get; set; }

    [NotNull]
    public virtual string Type { get; set; }

    [NotNull]
    public virtual Form Form { get; set; }

    public FormElement(string name, int position, string type)
    {
        Name = name;
        Position = position;
        Type = type;
    }

    public FormElement()
        : this("unknownFormElement", -1, TYPE_UNKNOWN)
    {

    }

}

And the "Form" class:

public class Form : Entity
{
    [NotNull]
    public virtual string Name { get; set; }

    public virtual IList<FormElement> FormElements { get; set; }

    public Form(string name)
    {
        Name = name;

        FormElements = new List<FormElement>();
    }

    public Form()
        : this("unknownWebform")
    { 

    }

    //public interface for getting, adding, deleting FormElement 
}

So, the view will need to render the "Form" and fill the elements with the value of the related "ProjectDetail".

So, the view gets passed in a "ProjectEditModel":

public class ProjectEditModel
{
    public Form Form;

    public Project Project;

    public ProjectViewModel() {}
}

The following view is strongly typed to "ProjectEditModel":

<% using (Html.BeginForm("Edit", "Project", FormMethod.Post))
   {%>

        <div>
        <fieldset>
            <legend>Edit Project</legend>

            <div class="editor-label">
                <%: Html.LabelFor(m => m.Project.Name) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(m => m.Project.Name)%>
            </div>

            <div class="editor-label">
                <%: Html.LabelFor(m => m.Project.Description)%>
            </div>
             <div class="editor-field">
                <%: Html.TextBoxFor(m => m.Project.Description)%>
            </div>

            <% 

                foreach (var formElement in Model.Form.FormElements)
                {   
                    if (formElement.Type.Equals(Domain.Model.FormElement.TYPE_CHAR))
                    { 
                    %>
                        <div class="editor-label">
                            <%: Html.Label(Model.Project.GetDetail(formElement.Name).Name)%>
                        </div>
                        <div class="editor-field">
                            <%: Html.TextBoxFor(m => m.Project.GetDetail(formElement.Name).Value)%>
                        </div>
                    <%
                    }
                    if (formElement.Type.Equals(Domain.Model.FormElement.TYPE_NUMERIC))
                    {

                    }
                }

            %>

            <p>
                <input type="hidden" name="Id" value="<%: Model.Project.Id %>" />
                <input type="submit" value="Save" />
            </p>

        </fieldset>
    </div>

<% } %>

This will render correctly and show a form element for every additional detail. But when I do POST back the model, the constructor will have been invoked and this way I loose all my references. PENG!

I have read, that MVC "just works" like this and I am willing to accept that, but how do I solve my problem then? You need anymore information?

Thanks very much, would really appreciate help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

偏爱你一生 2024-10-14 03:02:31

MVC 不会自动处理您尝试动态创建表单的方式。它不会将表单元素的集合绑定到集合,因为它无法区分它们。

尝试 这篇博文来处理动态集合渲染和模型绑定。

MVC won't automatically handle the way you are trying to dynamically create the form. It won't bind your collection of form elements to the collection as it has no way of distinguishing between them.

Try the methodology described in this blog post to handle dynamic collection rendering and model binding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文