ASP.NET MVC2 RenderAction 使父级松散 ViewModel 上下文

发布于 2024-09-13 03:13:57 字数 5436 浏览 0 评论 0原文

我是我的项目浏览器页面,我有 2 个子元素需要它们自己的控制器(而不仅仅是用户控件) - 上传和文件浏览器,因此我使用 Html.RenderAction(Action, Controller, param) 添加了它们。

然而问题是,浏览页面需要 ProjectViewModel,而上传使用 UploadViewModel 等。因此,通过使用这些 Html.RenderAction 元素,浏览页面似乎立即停止接收 ProjectViewModel - 我猜它会切换到 VM最后一个 RenderAction 的值。

我必须在路由中设置一些东西来确保这些已经强类型化的视图保留它们的上下文吗?

用代码更新:

另外,也许我必须明确声明要“上传”的模型是不同的?我不知道。

浏览器(包含上传和文件浏览器):

<%@ 
Page Title="" 
Language="C#" 
Inherits="System.Web.Mvc.ViewPage<CKD.Web.Files.ViewModels.ProjectViewModel>"
MasterPageFile="~/Views/Project/Project.Master" 
%>

<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
    <table>
<tr>
<td id="upload" style="width: 180px" class="ui-widget ui-widget-content ui-corner-all">
    <% Html.RenderAction("Index", "Upload", new {id = Model.Project.Id}); %>
</td>
<td id="fileBrowser" style="width: auto" class="ui-widget ui-widget-content ui-corner-all">
    <% Html.RenderAction("Index", "FileBrowser", new {id = Model.Project.Id}); %>
</td>
</tr>
</table>
</asp:Content>

上传视图:

<%@ 
Page Title="" 
Language="C#" 
Inherits="System.Web.Mvc.ViewPage<CKD.Web.Files.ViewModels.UploadViewModel>" 
MasterPageFile="~/Views/Shared/Control.master"
%>
<%@ Import Namespace="System.IO" %>

<asp:Content runat="server" ID="Scripts" ContentPlaceHolderID="Scripts">
</asp:Content>

<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
<div class="uploadControl" style="Margin: 8px">
<h2 style="Margin-Bottom: 0px">Upload</h2>
<hr />

<div id="accordion" style="display: block;">
    <h3><a href="#">Files</a></h3>
    <div>
        <div class="ui-widget-content ui-corner-all" style="min-height: 80px; margin: 4px">
            <% if(Model.Files != null) %>
                <% foreach(FileInfo f in Model.Files) {%>
                    <p><%= f.Name %></p>
                    <hr />
                <% } %>
        </div>
        <ul style="width: 10px; list-style-type:none">
            <li class="ui-widget ui-widget-button ui-corners-all">Clear</li>
            <li class="ui-widget ui-widget-button ui-corners-all">Add</li>
        </ul>
    </div>
    <h3><a href="#">Transmittal</a></h3>
    <div>
        <p>File here</p>
        <p style="width: auto; margin: 8px" class="ui-widget-button">Pick File...</p>
    </div>
    <h3><a href="#">Notification</a></h3>
    <div>
        <p>
        Stuff
        </p>
    </div>
</div>
<div>
<div class="ui-widget ui-corner-all ui-widget-active">Upload Files</div>
</div>

</div>
</asp:Content>

上传控制器:

using System.Web.Mvc;

namespace CKD.Web.Files.Controllers
{
    using System.Linq;
    using Models;
    using ViewModels;

    public class UploadController : Controller
    {
        private ICKDClientAreaRepository Repository { get; set; }
        private UploadViewModel _viewModel;

                        private UploadViewModel ViewModel
    {
        get { return _viewModel ?? (_viewModel = ViewModel = UploadViewModel.Default(Repository)); }
        set { _viewModel = value; }
    }

                    public UploadController(ICKDClientAreaRepository repository)
    {
        Repository = repository;
    }

        // GET
        public ActionResult Index(int id)
        {
            var project = Repository.Projects.Single(x => x.Id == id);
            ViewModel = UploadViewModel.ForProject(project, Repository);

            return View(ViewModel);
        }
    }
}

上传虚拟机:

namespace CKD.Web.Files.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web.Security;
    using Models;

    public class UploadViewModel
    {
        public Project Project { get; set; }
        public DirectoryInfo Directory { get; set; }
        public User Uploader { get; set; }
        public DateTime Time { get; set; }

        public List<FileInfo> Files { get; set; }
        public FileInfo Transmittal { get; set; }

        public List<User> NotificationList { get; set; }

                        public static UploadViewModel Default(ICKDClientAreaRepository fromRepository)
    {
        var project = fromRepository.Projects.First();

        return ForProject(project, fromRepository);
    }

                                                                public static UploadViewModel ForProject(Project project, ICKDClientAreaRepository fromRepository)
    {
        var dir = project.DirectoryName;
        var uploader = fromRepository.Users.Single(x => x.Username == Membership.GetUser().UserName);
        var time = DateTime.Now;
        var notification = project.Users.ToList();

        return new UploadViewModel
        {
            Project = project,
            Directory = new DirectoryInfo(dir),
            Uploader = uploader,
            Time = time,
            NotificationList = notification
        };
    }
    }
}

I'm my Project Browser page I have 2 sub-elements that warrant their own controller (and not simply a user-control) - Upload and FileBrowser, and so I've added them using Html.RenderAction(Action, Controller, param).

The problem however, is that the Browse page requires ProjectViewModel, where Upload uses UploadViewModel, etc. etc. So by having these Html.RenderAction elements, the Browse page seems to immediately stop receiving the ProjectViewModel - i'm guessing it switches to the VM of the last RenderAction.

Is there something I have to set up in routing to ensure these already strongly typed Views keep their contexts?

Update with code:

Also, maybe I have to explicitly state that the model going TO "Upload" is a different one? I dunno.

Browser (containing Upload and FileBrowser):

<%@ 
Page Title="" 
Language="C#" 
Inherits="System.Web.Mvc.ViewPage<CKD.Web.Files.ViewModels.ProjectViewModel>"
MasterPageFile="~/Views/Project/Project.Master" 
%>

<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
    <table>
<tr>
<td id="upload" style="width: 180px" class="ui-widget ui-widget-content ui-corner-all">
    <% Html.RenderAction("Index", "Upload", new {id = Model.Project.Id}); %>
</td>
<td id="fileBrowser" style="width: auto" class="ui-widget ui-widget-content ui-corner-all">
    <% Html.RenderAction("Index", "FileBrowser", new {id = Model.Project.Id}); %>
</td>
</tr>
</table>
</asp:Content>

Upload View:

<%@ 
Page Title="" 
Language="C#" 
Inherits="System.Web.Mvc.ViewPage<CKD.Web.Files.ViewModels.UploadViewModel>" 
MasterPageFile="~/Views/Shared/Control.master"
%>
<%@ Import Namespace="System.IO" %>

<asp:Content runat="server" ID="Scripts" ContentPlaceHolderID="Scripts">
</asp:Content>

<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
<div class="uploadControl" style="Margin: 8px">
<h2 style="Margin-Bottom: 0px">Upload</h2>
<hr />

<div id="accordion" style="display: block;">
    <h3><a href="#">Files</a></h3>
    <div>
        <div class="ui-widget-content ui-corner-all" style="min-height: 80px; margin: 4px">
            <% if(Model.Files != null) %>
                <% foreach(FileInfo f in Model.Files) {%>
                    <p><%= f.Name %></p>
                    <hr />
                <% } %>
        </div>
        <ul style="width: 10px; list-style-type:none">
            <li class="ui-widget ui-widget-button ui-corners-all">Clear</li>
            <li class="ui-widget ui-widget-button ui-corners-all">Add</li>
        </ul>
    </div>
    <h3><a href="#">Transmittal</a></h3>
    <div>
        <p>File here</p>
        <p style="width: auto; margin: 8px" class="ui-widget-button">Pick File...</p>
    </div>
    <h3><a href="#">Notification</a></h3>
    <div>
        <p>
        Stuff
        </p>
    </div>
</div>
<div>
<div class="ui-widget ui-corner-all ui-widget-active">Upload Files</div>
</div>

</div>
</asp:Content>

Upload Controller:

using System.Web.Mvc;

namespace CKD.Web.Files.Controllers
{
    using System.Linq;
    using Models;
    using ViewModels;

    public class UploadController : Controller
    {
        private ICKDClientAreaRepository Repository { get; set; }
        private UploadViewModel _viewModel;

                        private UploadViewModel ViewModel
    {
        get { return _viewModel ?? (_viewModel = ViewModel = UploadViewModel.Default(Repository)); }
        set { _viewModel = value; }
    }

                    public UploadController(ICKDClientAreaRepository repository)
    {
        Repository = repository;
    }

        // GET
        public ActionResult Index(int id)
        {
            var project = Repository.Projects.Single(x => x.Id == id);
            ViewModel = UploadViewModel.ForProject(project, Repository);

            return View(ViewModel);
        }
    }
}

Upload VM:

namespace CKD.Web.Files.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web.Security;
    using Models;

    public class UploadViewModel
    {
        public Project Project { get; set; }
        public DirectoryInfo Directory { get; set; }
        public User Uploader { get; set; }
        public DateTime Time { get; set; }

        public List<FileInfo> Files { get; set; }
        public FileInfo Transmittal { get; set; }

        public List<User> NotificationList { get; set; }

                        public static UploadViewModel Default(ICKDClientAreaRepository fromRepository)
    {
        var project = fromRepository.Projects.First();

        return ForProject(project, fromRepository);
    }

                                                                public static UploadViewModel ForProject(Project project, ICKDClientAreaRepository fromRepository)
    {
        var dir = project.DirectoryName;
        var uploader = fromRepository.Users.Single(x => x.Username == Membership.GetUser().UserName);
        var time = DateTime.Now;
        var notification = project.Users.ToList();

        return new UploadViewModel
        {
            Project = project,
            Directory = new DirectoryInfo(dir),
            Uploader = uploader,
            Time = time,
            NotificationList = notification
        };
    }
    }
}

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

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

发布评论

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

评论(1

计㈡愣 2024-09-20 03:13:57

尝试将 RenderAction() 渲染的视图设为分部视图。

您还应该使用 [ChildActionOnly] 属性装饰该操作,以防止它自己执行(当有人请求 http://xxx.com/Upload/Index 时) 。

Try making the view rendered by RenderAction() a partial view.

You should also decorate the action with [ChildActionOnly] attribute to prevent it from executing by it's own (when somebody would request http://xxx.com/Upload/Index).

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