Merge pull request #2287 from aspnet/ra-vc

View Components update
pull/2295/head
Rick Anderson 2016-12-01 11:25:36 -10:00 committed by GitHub
commit aa6b1a11eb
29 changed files with 419 additions and 190 deletions

View File

@ -1,11 +1,11 @@
---
title: View Components | Microsoft Docs
author: rick-anderson
description:
keywords: ASP.NET Core,
description: View Components are intended anywhere you have reusable rendering logic.
keywords: ASP.NET Core,view components, partial view
ms.author: riande
manager: wpickett
ms.date: 10/14/2016
ms.date: 12/14/2016
ms.topic: article
ms.assetid: ab4705b7-59d7-4f31-bc97-ea7f292fe926
ms.technology: aspnet
@ -14,9 +14,6 @@ uid: mvc/views/view-components
---
# View Components
>[!WARNING]
> This page documents version 1.0.0-rc1 and has not yet been updated for version 1.0.0
By [Rick Anderson](https://twitter.com/RickAndMSFT)
[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/mvc/views/view-components/sample)
@ -49,7 +46,7 @@ View Components are intended anywhere you have reusable rendering logic that is
* A login panel that would be rendered on every page and show either the links to log out or log in, depending on the log in state of the user
A `view component` consists of two parts, the class (typically derived from `ViewComponent`) and the result it returns (typically a view). Like controllers, a view component can be a POCO, but most developers will want to take advantage of the methods and properties available by deriving from `ViewComponent`.
A `view component` consists of two parts, the class (typically derived from [ViewComponent](https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.mvc.viewcomponent) and the result it returns (typically a view). Like controllers, a view component can be a POCO, but most developers will want to take advantage of the methods and properties available by deriving from `ViewComponent`.
## Creating a view component
@ -77,31 +74,27 @@ A view component class:
A view component defines its logic in an `InvokeAsync` method that returns an `IViewComponentResult`. Parameters come directly from invocation of the view component, not from model binding. A view component never directly handles a request. Typically a view component initializes a model and passes it to a view by calling the `View` method. In summary, view component methods:
* Define an *InvokeAsync`* method that returns an `IViewComponentResult`
* Define an *`InvokeAsync`* method that returns an `IViewComponentResult`
* Typically initializes a model and passes it to a view by calling the `ViewComponent` `View` method
* Parameters come from the calling method, not HTTP, there is no model binding
* Are not reachable directly as an HTTP endpoint, they are invoked from your code (usually in a view). A view component never handles a request
* Are overloaded on the signature rather than any details from the current HTTP request
### View search path
The runtime searches for the view in the following paths:
* Views/<controller_name>/Components/<view_component_name>/<view_name>
* Views/\<controller_name>/Components/\<view_component_name>/\<view_name>
* Views/Shared/Components/<view_component_name>/<view_name>
* Views/Shared/Components/\<view_component_name>/\<view_name>
The default view name for a view component is *Default*, which means your view file will typically be named *Default.cshtml*. You can specify a different view name when creating the view component result or when calling the `View` method.
We recommend you name the view file *Default.cshtml* and use the *Views/Shared/Components/<view_component_name>/<view_name>* path. The `PriorityList` view component used in this sample uses *Views/Shared/Components/PriorityList/Default.cshtml* for the view component view.
We recommend you name the view file *Default.cshtml* and use the *Views/Shared/Components/\<view_component_name>/\<view_name>* path. The `PriorityList` view component used in this sample uses *Views/Shared/Components/PriorityList/Default.cshtml* for the view component view.
## Invoking a view component
To use the view component, call `@Component.InvokeAsync("Name of view component", <anonymous type containing parameters>)` from a view. The parameters will be passed to the `InvokeAsync` method. The `PriorityList` view component developed in the article is invoked from the *Views/Todo/Index.cshtml* view file. In the following, the `InvokeAsync` method is called with two parameters:
To use the view component, call `@Component.InvokeAsync("Name of view component", \<anonymous type containing parameters>)` from a view. The parameters will be passed to the `InvokeAsync` method. The `PriorityList` view component developed in the article is invoked from the *Views/Todo/Index.cshtml* view file. In the following, the `InvokeAsync` method is called with two parameters:
```HTML
@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
@ -113,7 +106,7 @@ View components are typically invoked from a view, but you can invoke them direc
In this example, the view component is called directly from the controller:
[!code-csharp[Main](view-components/sample/ViewCompFinal/Controllers/ToDoController.cs?range=23-26)]
[!code-csharp[Main](view-components/sample/ViewCompFinal/Controllers/ToDoController.cs?name=snippet_IndexVC)]
## Walkthrough: Creating a simple view component
@ -125,58 +118,52 @@ In this example, the view component is called directly from the controller:
Create a *ViewComponents* folder and add the following `PriorityListViewComponent` class.
[!code-csharp[Main](view-components/sample/ViewCompFinal/ViewComponents/PriorityListViewComponent1.cs?range=3-33)]
[!code-csharp[Main](view-components/sample/ViewCompFinal/ViewComponents/PriorityListViewComponent1.cs?name=snippet1)]
Notes on the code:
* View component classes can be contained in **any** folder in the project.
* Because the class name `PriorityListViewComponent` ends with the suffix **ViewComponent**, the runtime will use the string "PriorityList" when referencing the class component from a view. I'll explain that in more detail later.
* Because the class name PriorityList**ViewComponent** ends with the suffix **ViewComponent**, the runtime will use the string "PriorityList" when referencing the class component from a view. I'll explain that in more detail later.
* The `[ViewComponent]` attribute can change the name used to reference a view component. For example, we could have named the class `XYZ`, and applied the `ViewComponent` attribute:
<!-- literal_block {"ids": [], "linenos": false, "xml:space": "preserve", "language": "csharp"} -->
```csharp
[ViewComponent(Name = "PriorityList")]
public class XYZ : ViewComponent
```
* The `[ViewComponent]` attribute above tells the view component selector to use the name `PriorityList` when looking for the views associated with the component, and to use the string "PriorityList" when referencing the class component from a view. I'll explain that in more detail later.
* The component uses [dependency injection](../../fundamentals/dependency-injection.md) to make the data context available.
* `InvokeAsync` exposes a method which can be called from a view, and it can take an arbitrary number of arguments.
* The `InvokeAsync` method returns the set of `ToDo` items that are not completed and have priority lower than or equal to `maxPriority`.
* The `InvokeAsync` method returns the set of `ToDo` items that satisfy the `isDone` and `maxPriority` parameters.
### Create the view component Razor view
1. Create the *Views/Shared/Components* folder. This folder **must** be named *Components*.
* Create the *Views/Shared/Components* folder. This folder **must** be named *Components*.
2. Create the *Views/Shared/Components/PriorityList* folder. This folder name must match the name of the view component class, or the name of the class minus the suffix (if we followed convention and used the *ViewComponent* suffix in the class name). If you used the `ViewComponent` attribute, the class name would need to match the attribute designation.
* Create the *Views/Shared/Components/PriorityList* folder. This folder name must match the name of the view component class, or the name of the class minus the suffix (if we followed convention and used the *ViewComponent* suffix in the class name). If you used the `ViewComponent` attribute, the class name would need to match the attribute designation.
3. Create a *Views/Shared/Components/PriorityList/Default.cshtml* Razor view.
[!code-html[Main](view-components/sample/ViewCompFinal/Views/Shared/Components/PriorityList/Default1.cshtml)]
* Create a *Views/Shared/Components/PriorityList/Default.cshtml* Razor view:
[!code-html[Main](view-components/sample/ViewCompFinal/Views/Shared/Components/PriorityList/Default1.cshtml)]
The Razor view takes a list of `TodoItem` and displays them. If the view component `InvokeAsync` method doesn't pass the name of the view (as in our sample), *Default* is used for the view name by convention. Later in the tutorial, I'll show you how to pass the name of the view. To override the default styling for a specific controller, add a view to the controller specific view folder (for example *Views/Todo/Components/PriorityList/Default.cshtml)*.
The Razor view takes a list of `TodoItem` and displays them. If the view component `InvokeAsync` method doesn't pass the name of the view (as in our sample), *Default* is used for the view name by convention. Later in the tutorial, I'll show you how to pass the name of the view. To override the default styling for a specific controller, add a view to the controller specific view folder (for example *Views/Todo/Components/PriorityList/Default.cshtml)*.
If the view component was controller specific, you could add it to the controller specific folder (*Views/Todo/Components/PriorityList/Default.cshtml*)
If the view component is controller specific, you can add it to the controller specific folder (*Views/Todo/Components/PriorityList/Default.cshtml*).
4. Add a `div` containing a call to the priority list component to the bottom of the *Views/Todo/index.cshtml* file:
* Add a `div` containing a call to the priority list component to the bottom of the *Views/Todo/index.cshtml* file:
[!code-html[Main](view-components/sample/ViewCompFinal/Views/Todo/IndexFirst.cshtml?range=34-38)]
The markup `@Component.InvokeAsync` shows the syntax for calling view components. The first argument is the name of the component we want to invoke or call. Subsequent parameters are passed to the component. `InvokeAsync` can take an arbitrary number of arguments.
The markup `@await Component.InvokeAsync` shows the syntax for calling view components. The first argument is the name of the component we want to invoke or call. Subsequent parameters are passed to the component. `InvokeAsync` can take an arbitrary number of arguments.
The following image shows the priority items:
Test the app. The following image shows the ToDo list and the priority items:
![image](view-components/_static/pi.png)
![todo list and priority items](view-components/_static/pi.png)
You can also call the view component directly from the controller:
[!code-csharp[Main](view-components/sample/ViewCompFinal/Controllers/ToDoController.cs?range=23-26)]
[!code-csharp[Main](view-components/sample/ViewCompFinal/Controllers/ToDoController.cs?name=snippet_IndexVC)]
![priority items from IndexVC action](view-components/_static/indexvc.png)
### Specifying a view name
@ -190,7 +177,9 @@ Copy the *Views/Shared/Components/PriorityList/Default.cshtml* file to a view na
Update *Views/TodoList/Index.cshtml*
[!code-html[Main](view-components/sample/ViewCompFinal/Views/Todo/IndexFinal.cshtml?range=31-)]
<!-- Views/TodoList/Index.cshtml is never imported, so change to test tutorial -->
[!code-html[Main](view-components/sample/ViewCompFinal/Views/Todo/IndexFinal.cshtml?range=35)]
Run the app and verify PVC view.
@ -200,31 +189,25 @@ If the PVC view is not rendered, verify you are calling the view component with
### Examine the view path
1. Change the priority parameter to three or less so the priority view is not returned.
2. Temporarily rename the *Views/Todo/Components/PriorityList/Default.cshtml* to *Temp.cshtml*.
3. Test the app, you'll get the following error:
* Change the priority parameter to three or less so the priority view is not returned.
* Temporarily rename the *Views/Todo/Components/PriorityList/Default.cshtml* to *1Default.cshtml*.
* Test the app, you'll get the following error:
<!-- literal_block {"ids": [], "xml:space": "preserve"} -->
```
An unhandled exception occurred while processing the request.
InvalidOperationException: The view 'Components/PriorityList/Default'
was not found. The following locations were searched:
/Views/ToDo/Components/PriorityList/Default.cshtml
/Views/Shared/Components/PriorityList/Default.cshtml.
Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful()
An unhandled exception occurred while processing the request.
InvalidOperationException: The view 'Components/PriorityList/Default' was not found. The following locations were searched:
/Views/ToDo/Components/PriorityList/Default.cshtml
/Views/Shared/Components/PriorityList/Default.cshtml
EnsureSuccessful
```
4. Copy *Views/Shared/Components/PriorityList/Default.cshtml to *Views/Todo/Components/PriorityList/Default.cshtml*.
* Copy *Views/Todo/Components/PriorityList/1Default.cshtml* to *Views/Shared/Components/PriorityList/Default.cshtml.
* Add some markup to the *Shared* Todo view component view to indicate the view is from the *Shared* folder.
* Test the **Shared** component view.
5. Add some markup to the *Todo* view component view to indicate the view is from the *Todo* folder.
6. Test the **non-shared** component view.
![image](view-components/_static/shared.png)
![ToDo output with Shared component view](view-components/_static/shared.png)
### Avoiding magic strings

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,5 +1,5 @@
using Microsoft.AspNet.Mvc;
using System.Linq;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.Controllers
@ -13,11 +13,14 @@ namespace ViewComponentSample.Controllers
_ToDoContext = context;
}
public IActionResult Index()
{
var model = _ToDoContext.ToDo.ToList();
return View(model);
}
public string Index2()
{
return "View()";
}
}
}

View File

@ -1,9 +1,15 @@
using Microsoft.Data.Entity;

using Microsoft.EntityFrameworkCore;
namespace ViewComponentSample.Models
{
public class ToDoContext : DbContext
{
public ToDoContext(DbContextOptions<ToDoContext> options)
: base(options)
{
}
public DbSet<TodoItem> ToDo { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
namespace ViewComponentSample
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -1,8 +1,8 @@
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using ViewComponentSample.Models;
using Microsoft.EntityFrameworkCore;
namespace ViewComponentSample
{
@ -10,22 +10,28 @@ namespace ViewComponentSample
{
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddInMemoryDatabase()
.AddDbContext<ToDoContext>( options =>
options.UseInMemoryDatabase());
services.AddDbContext<ToDoContext>(options =>
options.UseInMemoryDatabase());
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseIISPlatformHandler();
app.UseMvcWithDefaultRoute();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Todo}/{action=Index}/{id?}");
});
SeedData.Initialize(app.ApplicationServices);
}
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}

View File

@ -4,22 +4,20 @@
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>bd6112ed-41ee-49d1-afaf-95581d782ff5</ProjectGuid>
<ProjectGuid>91534ec5-dbc9-4325-bfa1-369bf811381a</ProjectGuid>
<RootNamespace>ViewComponentSample</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<DnxInvisibleContent Include="bower.json" />
<DnxInvisibleContent Include=".bowerrc" />
<DnxInvisibleContent Include="package.json" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,14 @@
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - ViewComponentSample</title>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">ViewComponentSample</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; 2016 - ViewComponentSample</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
</body>
</html>

View File

@ -1,33 +1,61 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"EntityFramework.Core": "7.0.0-rc1-final",
"EntityFramework.InMemory": "7.0.0-rc1-final",
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final"
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Razor.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
},
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.EntityFrameworkCore": "1.0.0",
"Microsoft.EntityFrameworkCore.InMemory": "1.0.0"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel"
"tools": {
"BundlerMinifier.Core": "2.0.238",
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {
"include": [
"wwwroot",
"Views",
"Areas/**/Views",
"appsettings.json",
"web.config"
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
-->
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
</system.webServer>
</configuration>

View File

@ -1,8 +1,8 @@
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace ViewComponentSample.Controllers
{
@ -17,13 +17,15 @@ namespace ViewComponentSample.Controllers
public IActionResult Index()
{
return View(_ToDoContext.ToDo.ToList());
var model = _ToDoContext.ToDo.ToList();
return View(model);
}
#region snippet_IndexVC
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
#endregion
public async Task<IActionResult> IndexFinal()
{

View File

@ -1,9 +1,15 @@
using Microsoft.Data.Entity;

using Microsoft.EntityFrameworkCore;
namespace ViewComponentSample.Models
{
public class ToDoContext : DbContext
{
public ToDoContext(DbContextOptions<ToDoContext> options)
: base(options)
{
}
public DbSet<TodoItem> ToDo { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
namespace ViewComponentSample
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}

View File

@ -1,8 +1,8 @@
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using ViewComponentSample.Models;
using Microsoft.EntityFrameworkCore;
namespace ViewComponentSample
{
@ -10,22 +10,28 @@ namespace ViewComponentSample
{
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddInMemoryDatabase()
.AddDbContext<ToDoContext>( options =>
options.UseInMemoryDatabase());
services.AddDbContext<ToDoContext>(options =>
options.UseInMemoryDatabase());
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseIISPlatformHandler();
app.UseMvcWithDefaultRoute();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Todo}/{action=Index}/{id?}");
});
SeedData.Initialize(app.ApplicationServices);
}
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}

View File

@ -4,22 +4,20 @@
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>bd6112ed-41ee-49d1-afaf-95581d782ff5</ProjectGuid>
<ProjectGuid>91534ec5-dbc9-4325-bfa1-369bf811381a</ProjectGuid>
<RootNamespace>ViewComponentSample</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<DnxInvisibleContent Include="bower.json" />
<DnxInvisibleContent Include=".bowerrc" />
<DnxInvisibleContent Include="package.json" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -1,8 +1,9 @@
#define no
#if no
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
// Used at the very end with Avoiding magic strings
//#define no_suffix
#if no_suffix
#region snippet1
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -32,6 +33,5 @@ namespace ViewComponentSample.ViewComponents
}
}
}
#endregion
#endif

View File

@ -1,8 +1,8 @@
//#define V0
#define V0
#if V0
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

View File

@ -1,7 +1,8 @@

//#define V1
#if V1
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
#region snippet1
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -24,13 +25,15 @@ namespace ViewComponentSample.ViewComponents
var items = await GetItemsAsync(maxPriority, isDone);
return View(items);
}
#region snippet2
private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
}
#endregion
}
}
#endregion
#endif

View File

@ -1,8 +1,8 @@
//#define Final
#if Final
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -24,7 +24,7 @@ namespace ViewComponentSample.ViewComponents
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
#region snippet1
public async Task<IViewComponentResult> InvokeAsync(
int maxPriority, bool isDone)
{
@ -37,6 +37,7 @@ namespace ViewComponentSample.ViewComponents
var items = await GetItemsAsync(maxPriority, isDone);
return View(MyView, items);
}
#endregion
}
}

View File

@ -1,9 +0,0 @@
@model IEnumerable<ViewComponentSample.Models.TodoItem>
<h3>Priority Items</h3>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>

View File

@ -0,0 +1,14 @@
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>

View File

@ -29,9 +29,9 @@
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
</tr>
}
</table>
<div >
<div>
@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
</div>

View File

@ -1,5 +1,4 @@

@using ViewComponentSample.Models
@using ViewComponentSample.Models
@model IEnumerable<TodoItem>
<h2>ToDo</h2>

View File

@ -1,33 +1,61 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"EntityFramework.Core": "7.0.0-rc1-final",
"EntityFramework.InMemory": "7.0.0-rc1-final",
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final"
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Razor.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
},
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.EntityFrameworkCore": "1.0.0",
"Microsoft.EntityFrameworkCore.InMemory": "1.0.0"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel"
"tools": {
"BundlerMinifier.Core": "2.0.238",
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {
"include": [
"wwwroot",
"Views",
"Areas/**/Views",
"appsettings.json",
"web.config"
]
},
"scripts": {
"prepublish": [ "bower install", "dotnet bundle" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
-->
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
</system.webServer>
</configuration>