简体   繁体   中英

Reusing a view in another view with parameters in ASP.NET MVC

Being rather new to ASP.NET MVC, I am already seeing some benefits of it for code reuse and maintainability. When asking a previous question on routing , I had another idea for my example, but unsure how to implement it.

Question: How can I reuse my issue view and controller in separate pages, as well as having parameters for certain things (like how many issues to display)?

Example: Say in my web application I want to show a list of issues. These issues are grouped by projects. So if you go to www.example.com/projectname/issues, you would see a list of issues for that project, and if you went to www.example.com/issues, you would see all issues for all projects. What I would like to do is that if you go to www.example.com/projectname, you would see some info about that project, including the last 10 issues submitted.

How can I reuse this issue code? I see I have the option for Partial View, but when I implemented it, I was unsure how to route any code to it. In Web Forms, you could make a ASP.net control, set some parameters in the code behind, and then embed this control elsewhere.

Some of the examples I have found so far either lack a complete implementation (goiing beyond just adding some HTMl in other pages), look like older MVC code that doesn't seem to work for me in ASP.NET MVC 3, and lack allowing me to set paramaters and showing this type of reuse.

My terminology may not be entirely correct here. If anything, I am trying to find the best (read MVC) way to replicate something like ASP.net Web Forms User Controls . As in, reusing my 'issues' code (HTML and C#) on both a 'master' issues list, as well as an issues 'widget' if you will

Skip the temptation write code in the view that goes out and accesses data on it's own. That includes using built-in functions like RenderAction. Even though RenderAction "goes back" to execute another controller it doesn't mean the view isn't taking an action on its own, which arguably breaks the MVC approach where views are supposed to do nothing and the model is supposed to contain everything the view needs.

Instead what you could do is send back a model for your issue list page(s) which contains a property containing the issues list:

public class IssueListModel {
    public List<Issue> Issues { get; set; }
}

Populate it in your issue list action:

public ActionResult IssueList(string projectName) // projectName may be null
{
    var issueListModel = new IssueListModel();

    issueListModel.Issues = SomeRepository.GetIssues(projectName); // whatever you need to send...


    return View(issueListModel);
}

Then on your list pages you could loop through it:

@foreach (var issue in Model.Issues) {
    <div>@issue.IssueName</div>
}

Or you could send the Issues collection down to a partial view:

@Html.RenderPartial("IssueList", Model.Issues)

You can type your partial view to expect List as the model:

@model List<MyProject.Models.Issue>

... and then loop through it in the partial view, this time doing a foreach on the model itself:

@foreach (var issue in Model) {
    <div>@issue.IssueName</div>
}

Then what you can do is make a separate model for your project detail view which also contains a property containing Issues:

public class ProjectDetailModel {
    public Project Project { get; set; }
    public List<Issue> Issues { get; set; }
    public string Whatever { get; set; }
}

In the controller you can populate this List using the same function that you would populate in your lists controller:

public ActionResult ProjectDetail(string projectName)
{
    var projectDetailModel = new ProjectDetailModel();

    projectDetailModel.Issues = SomeRepository.GetIssues(projectName, 10); // whatever you need to send


    return View(projectDetailModel);
}

Then you can re-use the same exact partial view on your ProjectDetail view:

@Html.RenderPartial("IssueList", Model.Issues)

A long answer but I hope this is what you were looking for!

If you want to re-use presentation logic only, you can use partial view. If you want to re-use also controller's logic, you have to use child action combined with partial view.

Create a controller

public class IssuesController : Controller
{
    [ChildActionOnly]
    public PartialViewResult List(string projectName, int issueCount = 0)
    {
        IEnumerable<Issue> issueList = new List<Issue>();

        // Here load appropriate issues into issueList

        return PartialView(issueList);
    }
}

Do not forget also to create appropriate partial view named List within the folder Issues.

Finally use this line within your project view

@{ Html.RenderAction("List", "Issues", new { projectName = "Px", issueCount = 10 } ); }

and this line within your issue list view

@{ Html.RenderAction("List", "Issues", new { projectName = "Px" } ); }

In your controller method return the view as named rather than just View()

ie...

public ViewResult IssueView1()
{ return View("Issue");}

public ViewResult IssueView2()
{return View("Issue");}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM