Compare commits

..

3 Commits

Author SHA1 Message Date
SteveSandersonMS
bd42deef7e Publish templates v0.6.2 2016-11-29 19:12:00 +00:00
SteveSandersonMS
939e0aeee0 Make 'fetchdata' components in templates compatible with latest TypeScript compiler 2016-11-29 19:10:48 +00:00
SteveSandersonMS
28b8136fa6 Detect legacy aspnet-prerendering mode earlier to fix #470 2016-11-29 17:23:14 +00:00
283 changed files with 3339 additions and 3765 deletions

3
.gitignore vendored
View File

@@ -13,6 +13,7 @@ PublishProfiles/
*.docstates
_ReSharper.*
nuget.exe
project.lock.json
*net45.csproj
*net451.csproj
*k10.csproj
@@ -38,5 +39,3 @@ npm-debug.log
/templates/*/ClientApp/dist/
/templates/*/yarn.lock
.vscode/
/templates/*/Properties/launchSettings.json

View File

@@ -10,10 +10,11 @@ addons:
- libssl-dev
- libunwind8
- zlib1g
mono: none
mono:
- 4.0.5
os:
- linux
- osx
osx_image: xcode7.1
script:
- ./build.sh
- ./build.sh verify

View File

@@ -1,68 +1,54 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{27304DDE-AFB2-4F8B-B765-E3E2F11E886C}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{E6E88944-4800-40BA-8AF5-069EA3ADFEB8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.NodeServices", "src\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj", "{66B77203-1469-41DF-92F2-2BE6900BD36F}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.NodeServices", "src\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.xproj", "{B0FA4175-8B29-4904-9780-28B3C24B0567}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.NodeServices.Sockets", "src\Microsoft.AspNetCore.NodeServices.Sockets\Microsoft.AspNetCore.NodeServices.Sockets.csproj", "{F46DEF99-6FAA-4406-B5D8-6FF34EF669E3}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NodeServicesExamples", "samples\misc\NodeServicesExamples\NodeServicesExamples.xproj", "{6D4BCDD6-7951-449B-BE55-CB7F014B7430}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SpaServices", "src\Microsoft.AspNetCore.SpaServices\Microsoft.AspNetCore.SpaServices.csproj", "{66B071A8-EFC8-4A06-BEF6-06B99AE27EEC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.AngularServices", "src\Microsoft.AspNetCore.AngularServices\Microsoft.AspNetCore.AngularServices.csproj", "{58AAABB6-9D21-42F6-BC97-3DD282B55FD6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ReactServices", "src\Microsoft.AspNetCore.ReactServices\Microsoft.AspNetCore.ReactServices.csproj", "{F1081B9A-8D67-4A5E-80C6-615F9A975D4F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{99EAF1FE-22C8-4526-BE78-74B24125D37F}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{78DAC76C-1092-45AB-BF0D-594B8C7B6569}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
global.json = global.json
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{23836492-E7F4-4376-85BF-A635C304AC46}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore", "samples\angular\MusicStore\MusicStore.xproj", "{1A74148F-9DC0-435D-B5AC-7D1B0D3D5E0B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{E6A161EA-646C-4033-9090-95BE809AB8D9}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ReactGrid", "samples\react\ReactGrid\ReactGrid.xproj", "{ABF90A5B-F4E0-438C-A6E4-9549FB43690B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LatencyTest", "samples\misc\LatencyTest\LatencyTest.csproj", "{1931B19A-EC42-4D56-B2D0-FB06D17244DA}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.AngularServices", "src\Microsoft.AspNetCore.AngularServices\Microsoft.AspNetCore.AngularServices.xproj", "{421807E6-B62C-417B-B901-46C5DEDAA8F1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Webpack", "samples\misc\Webpack\Webpack.csproj", "{DE479DC3-1461-4EAD-A188-4AF7AA4AE344}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.ReactServices", "src\Microsoft.AspNetCore.ReactServices\Microsoft.AspNetCore.ReactServices.xproj", "{B04381DE-991F-4831-A0B5-FE1BD3EF80C4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodeServicesExamples", "samples\misc\NodeServicesExamples\NodeServicesExamples.csproj", "{93EFCC5F-C6EE-4623-894F-A42B22C0B6FE}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.SpaServices", "src\Microsoft.AspNetCore.SpaServices\Microsoft.AspNetCore.SpaServices.xproj", "{4624F728-6DFF-44B6-93B5-3C7D9C94BF3F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "angular", "angular", "{B54435EB-D5E8-4CEC-A02E-DDCB0C750E34}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Templates", "Templates", "{727E6D58-6830-4792-96C6-E138A33959FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicStore", "samples\angular\MusicStore\MusicStore.csproj", "{63FC66E7-559B-4426-93E1-2D951EFC8293}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Angular2Spa", "templates\Angular2Spa\Angular2Spa.xproj", "{8F5CB8A9-3086-4B49-A1C2-32A9F89BCA11}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "react", "react", "{BD77E73E-13BC-4550-99DA-51869BD8DFC4}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ReactReduxSpa", "templates\ReactReduxSpa\ReactReduxSpa.xproj", "{DBFC6DB0-A6D1-4694-A108-1C604B988DA3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactGrid", "samples\react\ReactGrid\ReactGrid.csproj", "{3B023106-88DB-4C3A-B01F-C1AECB02D80B}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ReactSpa", "templates\ReactSpa\ReactSpa.xproj", "{E9D1A695-F0E6-46F2-B5E3-72F4AF805387}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicStore", "samples\react\MusicStore\MusicStore.csproj", "{6E898586-79CA-4AA8-946E-943B3682F376}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "WebApplicationBasic", "templates\WebApplicationBasic\WebApplicationBasic.xproj", "{CB4398D6-B7F1-449A-AE02-828769679232}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{1598B415-73F1-4B37-B3B4-0A10677ABB2D}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{E0771531-BE20-40CD-A1B0-A57E09511060}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KnockoutSpa", "templates\KnockoutSpa\KnockoutSpa.csproj", "{F60248B1-940E-43FB-BEA0-589362AA6320}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Webpack", "samples\misc\Webpack\Webpack.xproj", "{A8905301-8492-42FD-9E83-F715A0FDC3A2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Angular2Spa", "templates\Angular2Spa\Angular2Spa.csproj", "{4D4B84C9-13F7-40CA-B05A-DC98FD6019AC}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "LatencyTest", "samples\misc\LatencyTest\LatencyTest.xproj", "{A64AF9D9-72AA-4433-BE1D-DC2524B6808A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AureliaSpa", "templates\AureliaSpa\AureliaSpa.csproj", "{4D57B6E1-7141-48ED-959E-872BDD4A2F72}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "React", "React", "{E0EBA813-4478-4C02-B11D-FB3793113FE4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactSpa", "templates\ReactSpa\ReactSpa.csproj", "{868A630E-C61B-4807-B7A8-7EB53BE1C28A}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore", "samples\react\MusicStore\MusicStore.xproj", "{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactReduxSpa", "templates\ReactReduxSpa\ReactReduxSpa.csproj", "{9D4D15A1-A25B-44EC-AB63-F1CE9986712E}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Angular", "Angular", "{4867A616-83D6-48DC-964D-6AE743596631}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApplicationBasic", "templates\WebApplicationBasic\WebApplicationBasic.csproj", "{86911E07-C733-4C18-B49F-9A007A651246}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Aurelia", "templates\AureliaSpa\Aurelia.xproj", "{33D8DAD9-74F9-471D-8BAD-55F828FAA736}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{E415FE14-13B0-469F-836D-95059E6BAA6E}"
ProjectSection(SolutionItems) = preProject
src\build\common.props = src\build\common.props
src\build\Key.snk = src\build\Key.snk
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VueSpa", "templates\VueSpa\VueSpa.csproj", "{49D7665A-20EC-43FC-B8E8-EA0204F2D8C3}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "KnockoutSpa", "templates\KnockoutSpa\KnockoutSpa.xproj", "{85231B41-6998-49AE-ABD2-5124C83DBEF2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -70,104 +56,89 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{66B77203-1469-41DF-92F2-2BE6900BD36F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66B77203-1469-41DF-92F2-2BE6900BD36F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66B77203-1469-41DF-92F2-2BE6900BD36F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66B77203-1469-41DF-92F2-2BE6900BD36F}.Release|Any CPU.Build.0 = Release|Any CPU
{F46DEF99-6FAA-4406-B5D8-6FF34EF669E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F46DEF99-6FAA-4406-B5D8-6FF34EF669E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F46DEF99-6FAA-4406-B5D8-6FF34EF669E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F46DEF99-6FAA-4406-B5D8-6FF34EF669E3}.Release|Any CPU.Build.0 = Release|Any CPU
{66B071A8-EFC8-4A06-BEF6-06B99AE27EEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66B071A8-EFC8-4A06-BEF6-06B99AE27EEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66B071A8-EFC8-4A06-BEF6-06B99AE27EEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66B071A8-EFC8-4A06-BEF6-06B99AE27EEC}.Release|Any CPU.Build.0 = Release|Any CPU
{58AAABB6-9D21-42F6-BC97-3DD282B55FD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58AAABB6-9D21-42F6-BC97-3DD282B55FD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58AAABB6-9D21-42F6-BC97-3DD282B55FD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58AAABB6-9D21-42F6-BC97-3DD282B55FD6}.Release|Any CPU.Build.0 = Release|Any CPU
{F1081B9A-8D67-4A5E-80C6-615F9A975D4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1081B9A-8D67-4A5E-80C6-615F9A975D4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1081B9A-8D67-4A5E-80C6-615F9A975D4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1081B9A-8D67-4A5E-80C6-615F9A975D4F}.Release|Any CPU.Build.0 = Release|Any CPU
{1931B19A-EC42-4D56-B2D0-FB06D17244DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1931B19A-EC42-4D56-B2D0-FB06D17244DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1931B19A-EC42-4D56-B2D0-FB06D17244DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1931B19A-EC42-4D56-B2D0-FB06D17244DA}.Release|Any CPU.Build.0 = Release|Any CPU
{DE479DC3-1461-4EAD-A188-4AF7AA4AE344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE479DC3-1461-4EAD-A188-4AF7AA4AE344}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE479DC3-1461-4EAD-A188-4AF7AA4AE344}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE479DC3-1461-4EAD-A188-4AF7AA4AE344}.Release|Any CPU.Build.0 = Release|Any CPU
{93EFCC5F-C6EE-4623-894F-A42B22C0B6FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93EFCC5F-C6EE-4623-894F-A42B22C0B6FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93EFCC5F-C6EE-4623-894F-A42B22C0B6FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93EFCC5F-C6EE-4623-894F-A42B22C0B6FE}.Release|Any CPU.Build.0 = Release|Any CPU
{63FC66E7-559B-4426-93E1-2D951EFC8293}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63FC66E7-559B-4426-93E1-2D951EFC8293}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63FC66E7-559B-4426-93E1-2D951EFC8293}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63FC66E7-559B-4426-93E1-2D951EFC8293}.Release|Any CPU.Build.0 = Release|Any CPU
{3B023106-88DB-4C3A-B01F-C1AECB02D80B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B023106-88DB-4C3A-B01F-C1AECB02D80B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B023106-88DB-4C3A-B01F-C1AECB02D80B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B023106-88DB-4C3A-B01F-C1AECB02D80B}.Release|Any CPU.Build.0 = Release|Any CPU
{6E898586-79CA-4AA8-946E-943B3682F376}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E898586-79CA-4AA8-946E-943B3682F376}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E898586-79CA-4AA8-946E-943B3682F376}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E898586-79CA-4AA8-946E-943B3682F376}.Release|Any CPU.Build.0 = Release|Any CPU
{F60248B1-940E-43FB-BEA0-589362AA6320}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F60248B1-940E-43FB-BEA0-589362AA6320}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F60248B1-940E-43FB-BEA0-589362AA6320}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F60248B1-940E-43FB-BEA0-589362AA6320}.Release|Any CPU.Build.0 = Release|Any CPU
{4D4B84C9-13F7-40CA-B05A-DC98FD6019AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4D4B84C9-13F7-40CA-B05A-DC98FD6019AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D4B84C9-13F7-40CA-B05A-DC98FD6019AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4D4B84C9-13F7-40CA-B05A-DC98FD6019AC}.Release|Any CPU.Build.0 = Release|Any CPU
{4D57B6E1-7141-48ED-959E-872BDD4A2F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4D57B6E1-7141-48ED-959E-872BDD4A2F72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D57B6E1-7141-48ED-959E-872BDD4A2F72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4D57B6E1-7141-48ED-959E-872BDD4A2F72}.Release|Any CPU.Build.0 = Release|Any CPU
{868A630E-C61B-4807-B7A8-7EB53BE1C28A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{868A630E-C61B-4807-B7A8-7EB53BE1C28A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{868A630E-C61B-4807-B7A8-7EB53BE1C28A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{868A630E-C61B-4807-B7A8-7EB53BE1C28A}.Release|Any CPU.Build.0 = Release|Any CPU
{9D4D15A1-A25B-44EC-AB63-F1CE9986712E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D4D15A1-A25B-44EC-AB63-F1CE9986712E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D4D15A1-A25B-44EC-AB63-F1CE9986712E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D4D15A1-A25B-44EC-AB63-F1CE9986712E}.Release|Any CPU.Build.0 = Release|Any CPU
{86911E07-C733-4C18-B49F-9A007A651246}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86911E07-C733-4C18-B49F-9A007A651246}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86911E07-C733-4C18-B49F-9A007A651246}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86911E07-C733-4C18-B49F-9A007A651246}.Release|Any CPU.Build.0 = Release|Any CPU
{49D7665A-20EC-43FC-B8E8-EA0204F2D8C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{49D7665A-20EC-43FC-B8E8-EA0204F2D8C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49D7665A-20EC-43FC-B8E8-EA0204F2D8C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49D7665A-20EC-43FC-B8E8-EA0204F2D8C3}.Release|Any CPU.Build.0 = Release|Any CPU
{B0FA4175-8B29-4904-9780-28B3C24B0567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0FA4175-8B29-4904-9780-28B3C24B0567}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0FA4175-8B29-4904-9780-28B3C24B0567}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0FA4175-8B29-4904-9780-28B3C24B0567}.Release|Any CPU.Build.0 = Release|Any CPU
{6D4BCDD6-7951-449B-BE55-CB7F014B7430}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D4BCDD6-7951-449B-BE55-CB7F014B7430}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D4BCDD6-7951-449B-BE55-CB7F014B7430}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D4BCDD6-7951-449B-BE55-CB7F014B7430}.Release|Any CPU.Build.0 = Release|Any CPU
{1A74148F-9DC0-435D-B5AC-7D1B0D3D5E0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A74148F-9DC0-435D-B5AC-7D1B0D3D5E0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A74148F-9DC0-435D-B5AC-7D1B0D3D5E0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A74148F-9DC0-435D-B5AC-7D1B0D3D5E0B}.Release|Any CPU.Build.0 = Release|Any CPU
{ABF90A5B-F4E0-438C-A6E4-9549FB43690B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABF90A5B-F4E0-438C-A6E4-9549FB43690B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABF90A5B-F4E0-438C-A6E4-9549FB43690B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABF90A5B-F4E0-438C-A6E4-9549FB43690B}.Release|Any CPU.Build.0 = Release|Any CPU
{421807E6-B62C-417B-B901-46C5DEDAA8F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{421807E6-B62C-417B-B901-46C5DEDAA8F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{421807E6-B62C-417B-B901-46C5DEDAA8F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{421807E6-B62C-417B-B901-46C5DEDAA8F1}.Release|Any CPU.Build.0 = Release|Any CPU
{B04381DE-991F-4831-A0B5-FE1BD3EF80C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B04381DE-991F-4831-A0B5-FE1BD3EF80C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B04381DE-991F-4831-A0B5-FE1BD3EF80C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B04381DE-991F-4831-A0B5-FE1BD3EF80C4}.Release|Any CPU.Build.0 = Release|Any CPU
{4624F728-6DFF-44B6-93B5-3C7D9C94BF3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4624F728-6DFF-44B6-93B5-3C7D9C94BF3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4624F728-6DFF-44B6-93B5-3C7D9C94BF3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4624F728-6DFF-44B6-93B5-3C7D9C94BF3F}.Release|Any CPU.Build.0 = Release|Any CPU
{8F5CB8A9-3086-4B49-A1C2-32A9F89BCA11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8F5CB8A9-3086-4B49-A1C2-32A9F89BCA11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F5CB8A9-3086-4B49-A1C2-32A9F89BCA11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F5CB8A9-3086-4B49-A1C2-32A9F89BCA11}.Release|Any CPU.Build.0 = Release|Any CPU
{DBFC6DB0-A6D1-4694-A108-1C604B988DA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBFC6DB0-A6D1-4694-A108-1C604B988DA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBFC6DB0-A6D1-4694-A108-1C604B988DA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBFC6DB0-A6D1-4694-A108-1C604B988DA3}.Release|Any CPU.Build.0 = Release|Any CPU
{E9D1A695-F0E6-46F2-B5E3-72F4AF805387}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9D1A695-F0E6-46F2-B5E3-72F4AF805387}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9D1A695-F0E6-46F2-B5E3-72F4AF805387}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9D1A695-F0E6-46F2-B5E3-72F4AF805387}.Release|Any CPU.Build.0 = Release|Any CPU
{CB4398D6-B7F1-449A-AE02-828769679232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB4398D6-B7F1-449A-AE02-828769679232}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB4398D6-B7F1-449A-AE02-828769679232}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB4398D6-B7F1-449A-AE02-828769679232}.Release|Any CPU.Build.0 = Release|Any CPU
{A8905301-8492-42FD-9E83-F715A0FDC3A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8905301-8492-42FD-9E83-F715A0FDC3A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8905301-8492-42FD-9E83-F715A0FDC3A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8905301-8492-42FD-9E83-F715A0FDC3A2}.Release|Any CPU.Build.0 = Release|Any CPU
{A64AF9D9-72AA-4433-BE1D-DC2524B6808A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A64AF9D9-72AA-4433-BE1D-DC2524B6808A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A64AF9D9-72AA-4433-BE1D-DC2524B6808A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A64AF9D9-72AA-4433-BE1D-DC2524B6808A}.Release|Any CPU.Build.0 = Release|Any CPU
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Release|Any CPU.Build.0 = Release|Any CPU
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Release|Any CPU.Build.0 = Release|Any CPU
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{66B77203-1469-41DF-92F2-2BE6900BD36F} = {27304DDE-AFB2-4F8B-B765-E3E2F11E886C}
{F46DEF99-6FAA-4406-B5D8-6FF34EF669E3} = {27304DDE-AFB2-4F8B-B765-E3E2F11E886C}
{66B071A8-EFC8-4A06-BEF6-06B99AE27EEC} = {27304DDE-AFB2-4F8B-B765-E3E2F11E886C}
{58AAABB6-9D21-42F6-BC97-3DD282B55FD6} = {27304DDE-AFB2-4F8B-B765-E3E2F11E886C}
{F1081B9A-8D67-4A5E-80C6-615F9A975D4F} = {27304DDE-AFB2-4F8B-B765-E3E2F11E886C}
{E6A161EA-646C-4033-9090-95BE809AB8D9} = {23836492-E7F4-4376-85BF-A635C304AC46}
{1931B19A-EC42-4D56-B2D0-FB06D17244DA} = {E6A161EA-646C-4033-9090-95BE809AB8D9}
{DE479DC3-1461-4EAD-A188-4AF7AA4AE344} = {E6A161EA-646C-4033-9090-95BE809AB8D9}
{93EFCC5F-C6EE-4623-894F-A42B22C0B6FE} = {E6A161EA-646C-4033-9090-95BE809AB8D9}
{B54435EB-D5E8-4CEC-A02E-DDCB0C750E34} = {23836492-E7F4-4376-85BF-A635C304AC46}
{63FC66E7-559B-4426-93E1-2D951EFC8293} = {B54435EB-D5E8-4CEC-A02E-DDCB0C750E34}
{BD77E73E-13BC-4550-99DA-51869BD8DFC4} = {23836492-E7F4-4376-85BF-A635C304AC46}
{3B023106-88DB-4C3A-B01F-C1AECB02D80B} = {BD77E73E-13BC-4550-99DA-51869BD8DFC4}
{6E898586-79CA-4AA8-946E-943B3682F376} = {BD77E73E-13BC-4550-99DA-51869BD8DFC4}
{F60248B1-940E-43FB-BEA0-589362AA6320} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{4D4B84C9-13F7-40CA-B05A-DC98FD6019AC} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{4D57B6E1-7141-48ED-959E-872BDD4A2F72} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{868A630E-C61B-4807-B7A8-7EB53BE1C28A} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{9D4D15A1-A25B-44EC-AB63-F1CE9986712E} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{86911E07-C733-4C18-B49F-9A007A651246} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{E415FE14-13B0-469F-836D-95059E6BAA6E} = {27304DDE-AFB2-4F8B-B765-E3E2F11E886C}
{49D7665A-20EC-43FC-B8E8-EA0204F2D8C3} = {1598B415-73F1-4B37-B3B4-0A10677ABB2D}
{6D4BCDD6-7951-449B-BE55-CB7F014B7430} = {E0771531-BE20-40CD-A1B0-A57E09511060}
{1A74148F-9DC0-435D-B5AC-7D1B0D3D5E0B} = {4867A616-83D6-48DC-964D-6AE743596631}
{ABF90A5B-F4E0-438C-A6E4-9549FB43690B} = {E0EBA813-4478-4C02-B11D-FB3793113FE4}
{8F5CB8A9-3086-4B49-A1C2-32A9F89BCA11} = {727E6D58-6830-4792-96C6-E138A33959FB}
{DBFC6DB0-A6D1-4694-A108-1C604B988DA3} = {727E6D58-6830-4792-96C6-E138A33959FB}
{E9D1A695-F0E6-46F2-B5E3-72F4AF805387} = {727E6D58-6830-4792-96C6-E138A33959FB}
{CB4398D6-B7F1-449A-AE02-828769679232} = {727E6D58-6830-4792-96C6-E138A33959FB}
{E0771531-BE20-40CD-A1B0-A57E09511060} = {E6E88944-4800-40BA-8AF5-069EA3ADFEB8}
{A8905301-8492-42FD-9E83-F715A0FDC3A2} = {E0771531-BE20-40CD-A1B0-A57E09511060}
{A64AF9D9-72AA-4433-BE1D-DC2524B6808A} = {E0771531-BE20-40CD-A1B0-A57E09511060}
{E0EBA813-4478-4C02-B11D-FB3793113FE4} = {E6E88944-4800-40BA-8AF5-069EA3ADFEB8}
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C} = {E0EBA813-4478-4C02-B11D-FB3793113FE4}
{4867A616-83D6-48DC-964D-6AE743596631} = {E6E88944-4800-40BA-8AF5-069EA3ADFEB8}
{33D8DAD9-74F9-471D-8BAD-55F828FAA736} = {727E6D58-6830-4792-96C6-E138A33959FB}
{85231B41-6998-49AE-ABD2-5124C83DBEF2} = {727E6D58-6830-4792-96C6-E138A33959FB}
EndGlobalSection
EndGlobal

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />
<add key="AspNetCoreTools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json" />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

8
NuGet.master.config Executable file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="AspNetVNext" value="https://www.myget.org/f/aspnetmaster/api/v3/index.json" />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@@ -1,7 +1,5 @@
# JavaScriptServices
AppVeyor: [![AppVeyor](https://ci.appveyor.com/api/projects/status/gprilrckx116vc9m/branch/dev?svg=true)](https://ci.appveyor.com/project/aspnetci/javascriptservices/branch/dev)
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
## What is this?

View File

@@ -1,47 +1,7 @@
init:
- git config --global core.autocrlf true
install:
- ps: Install-Product node 6.9.2 x64
# .NET Core SDK binaries
# Download .NET Core SDK and add to PATH
- ps: $urlCurrent = "https://go.microsoft.com/fwlink/?LinkID=834991"
- ps: $urlPreview = "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/rel-1.0.0/dotnet-dev-win-x64.latest.zip"
- ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetsdk"
- ps: mkdir $env:DOTNET_INSTALL_DIR -Force | Out-Null
- ps: $tempFileCurrent = [System.IO.Path]::GetTempFileName()
- ps: $tempFilePreview = [System.IO.Path]::GetTempFileName()
- ps: (New-Object System.Net.WebClient).DownloadFile($urlCurrent, $tempFileCurrent)
- ps: (New-Object System.Net.WebClient).DownloadFile($urlPreview, $tempFilePreview)
- ps: Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory($tempFileCurrent, $env:DOTNET_INSTALL_DIR)
- ps: Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory($tempFilePreview, $env:DOTNET_INSTALL_DIR + "preview")
- ps: Copy-Item "${env:DOTNET_INSTALL_DIR}preview\*" "${env:DOTNET_INSTALL_DIR}" -Force -Recurse
- ps: $env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path"
build_script:
- ps: Push-Location
- cd templates/package-builder
- npm install
- npm run build
- ps: Pop-Location
artifacts:
- path: templates\package-builder\dist\artifacts\generator-aspnetcore-spa.tar.gz
name: generator-aspnetcore-spa
- path: templates\package-builder\dist\artifacts\*.nupkg
name: Microsoft.AspNetCore.SpaTemplates
type: NuGetPackage
# - ps: .\build.ps1
- build.cmd verify
clone_depth: 1
test_script:
# - dotnet restore ./src
# - npm install -g selenium-standalone
# - selenium-standalone install
# The nosys flag is needed for selenium to work on Appveyor
# - ps: Start-Process selenium-standalone 'start','--','-Djna.nosys=true'
# - ps: Push-Location
# - cd test
# - npm install
# - npm test
on_finish :
# - ps: Pop-Location
# After running tests, upload results to Appveyor
# - ps: (new-object net.webclient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\test\tmp\junit\*.xml))
test: off
deploy: off

View File

@@ -64,4 +64,4 @@ if (!(Test-Path $buildFolder)) {
}
}
&"$buildFile" @args
&"$buildFile" $args

View File

@@ -1,18 +0,0 @@
<Project>
<Import Project="dependencies.props" />
<PropertyGroup>
<Product>Microsoft ASP.NET Core</Product>
<RepositoryUrl>https://github.com/aspnet/javascriptservices</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" Version="1.0.1-*" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@@ -1,13 +0,0 @@
<Project>
<PropertyGroup>
<AspNetCoreVersion>1.1.0</AspNetCoreVersion>
<AspNetCoreMvcVersion>1.1.1</AspNetCoreMvcVersion>
<AspNetCoreToolsVersion>1.0.0-msbuild3-final</AspNetCoreToolsVersion>
<AutoMapperVersion>5.0.2</AutoMapperVersion>
<CoreFxVersion>4.3.0</CoreFxVersion>
<JsonNetVersion>10.0.1</JsonNetVersion>
<MicrosoftDataflowVersion>4.5.24</MicrosoftDataflowVersion>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<ThreadingDataflowVersion>4.7.0</ThreadingDataflowVersion>
</PropertyGroup>
</Project>

View File

@@ -1,12 +0,0 @@
<Project>
<Target Name="NpmRestore" AfterTargets="Restore" Condition="'$(PreflightRestore)' != 'true'">
<ItemGroup>
<NpmModules Include="$(RepositoryRoot)**\package.json"
Exclude="$(RepositoryRoot)**\node_modules\**\*" />
</ItemGroup>
<Message Text="Restoring NPM modules for: %0A - @(NpmModules -> '%(FullPath)','%0A - ')" Importance="high" />
<Exec Command="npm install" WorkingDirectory="%(NpmModules.RootDir)%(Directory)" />
</Target>
</Project>

3
global.json Normal file
View File

@@ -0,0 +1,3 @@
{
"projects": ["src"]
}

8
makefile.shade Executable file
View File

@@ -0,0 +1,8 @@
var VERSION='0.1'
var FULL_VERSION='0.1'
var AUTHORS='Microsoft Open Technologies, Inc.'
var SAMPLES_PROJECT_GLOB='templates/*/project.json'
use-standard-lifecycle
k-standard-goals

22
pack-local.sh Executable file
View File

@@ -0,0 +1,22 @@
versionSuffix=$1
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
projects=(
./src/Microsoft.AspNetCore.NodeServices
./src/Microsoft.AspNetCore.SpaServices
./src/Microsoft.AspNetCore.AngularServices
./src/Microsoft.AspNetCore.ReactServices
)
if [ -z "$versionSuffix" ]; then
echo "Usage: pack-local.sh <versionsuffix>"
echo "Example: pack-local.sh beta-000001"
exit 1
fi
pushd $dir > /dev/null
for proj in "${projects[@]}"; do
dotnet pack $proj --version-suffix $versionSuffix -o ./artifacts/
done
popd > /dev/null

View File

@@ -1,6 +1,7 @@
/node_modules/
/wwwroot/lib/
/wwwroot/ng-app/**/*.js
/project.lock.json
/music-db.sqlite
/Properties/launchSettings.json

View File

@@ -1,31 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.AngularServices\Microsoft.AspNetCore.AngularServices.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SQLite" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="AutoMapper" Version="$(AutoMapperVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="npm install" />
<Exec Command="gulp" />
</Target>
</Project>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>1a74148f-9dc0-435d-b5ac-7d1b0d3d5e0b</ProjectGuid>
<RootNamespace>MusicStore</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>5068</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,79 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"tooling": {
"defaultNamespace": "MusicStore"
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.1",
"type": "platform"
},
"Microsoft.AspNetCore.AngularServices": "1.0.0-*",
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.1",
"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.1",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"AutoMapper": "5.0.2"
},
"tools": {
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"publishOptions": {
"include": [
"appsettings.json",
"ClientApp",
"node_modules",
"typings",
"Views",
"tsconfig.json",
"tsd.json",
"web.config",
"webpack.*.js",
"wwwroot"
]
},
"scripts": {
"prepublish": [
"npm install",
"gulp"
],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.NodeServices.Sockets\Microsoft.AspNetCore.NodeServices.Sockets.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(AspNetCoreVersion)" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>a64af9d9-72aa-4433-be1d-dc2524b6808a</ProjectGuid>
<RootNamespace>LatencyTest</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -3,7 +3,6 @@ using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.NodeServices;
using Microsoft.AspNetCore.NodeServices.Sockets;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApplication
@@ -17,10 +16,7 @@ namespace ConsoleApplication
// Set up the DI system
var services = new ServiceCollection();
services.AddNodeServices(options => {
// To compare with Socket hosting, uncomment the following line
// Since .NET Core 1.1, the HTTP hosting model has become basically as fast as the Socket hosting model
//options.UseSocketHosting();
options.HostingModel = NodeServicesOptions.DefaultNodeHostingModel;
options.ProjectPath = Directory.GetCurrentDirectory();
options.WatchFileExtensions = new string[] {}; // Don't watch anything
});

View File

@@ -0,0 +1,19 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.NodeServices": "1.0.0-*",
"Microsoft.Extensions.DependencyInjection": "1.0.0"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
}

View File

@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.NodeServices;
namespace NodeServicesExamples.Controllers
{
@@ -16,21 +15,8 @@ namespace NodeServicesExamples.Controllers
return View();
}
public async Task<IActionResult> Chart([FromServices] INodeServices nodeServices)
public IActionResult ImageResizing()
{
var options = new { width = 400, height = 200, showArea = true, showPoint = true, fullWidth = true };
var data = new
{
labels = new[] { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
series = new[] {
new[] { 1, 5, 2, 5, 4, 3 },
new[] { 2, 3, 4, 8, 1, 2 },
new[] { 5, 4, 3, 2, 1, 0 }
}
};
ViewData["ChartMarkup"] = await nodeServices.InvokeAsync<string>("./Node/renderChart", "line", options, data);
return View();
}

View File

@@ -0,0 +1,64 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.NodeServices;
using Microsoft.AspNetCore.StaticFiles;
namespace NodeServicesExamples.Controllers
{
public class ResizeImageController : Controller
{
private const int MaxDimension = 1000;
private static string[] AllowedMimeTypes = new[] { "image/jpeg", "image/png", "image/gif" };
private IHostingEnvironment _environment;
private INodeServices _nodeServices;
public ResizeImageController(IHostingEnvironment environment, INodeServices nodeServices)
{
_environment = environment;
_nodeServices = nodeServices;
}
[Route("resize/{*imagePath}")]
public async Task<IActionResult> Index(string imagePath, int maxWidth, int maxHeight)
{
// Validate incoming params
if (maxWidth < 0 || maxHeight < 0 || maxWidth > MaxDimension || maxHeight > MaxDimension
|| (maxWidth + maxHeight) == 0)
{
return BadRequest("Invalid dimensions");
}
var mimeType = GetContentType(imagePath);
if (Array.IndexOf(AllowedMimeTypes, mimeType) < 0)
{
return BadRequest("Disallowed image format");
}
// Locate source image on disk
var fileInfo = _environment.WebRootFileProvider.GetFileInfo(imagePath);
if (!fileInfo.Exists)
{
return NotFound();
}
// Invoke Node and pipe the result to the response
var imageStream = await _nodeServices.InvokeAsync<Stream>(
"./Node/resizeImage",
fileInfo.PhysicalPath,
mimeType,
maxWidth,
maxHeight);
return File(imageStream, mimeType);
}
private string GetContentType(string path)
{
string result;
return new FileExtensionContentTypeProvider().TryGetContentType(path, out result) ? result : null;
}
}
}

View File

@@ -1,8 +0,0 @@
var generate = require('node-chartist');
module.exports = function (callback, type, options, data) {
generate(type, options, data).then(
result => callback(null, result), // Success case
error => callback(error) // Error case
);
};

View File

@@ -0,0 +1,8 @@
var sharp = require('sharp');
module.exports = function(result, physicalPath, mimeType, maxWidth, maxHeight) {
// Invoke the 'sharp' NPM module, and have it pipe the resulting image data back to .NET
sharp(physicalPath)
.resize(maxWidth || null, maxHeight || null)
.pipe(result.stream);
}

View File

@@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="npm install" />
</Target>
</Project>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>6d4bcdd6-7951-449b-be55-cb7f014b7430</ProjectGuid>
<RootNamespace>NodeServicesExamples</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\JavaScriptServices.sln\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>2018</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -1,12 +0,0 @@
<h1>Server-rendered chart</h1>
<p>
This sample demonstrates how arbitrary NPM modules can be invoked from .NET code.
</p>
<p>
In this case, we use <code>node-chartist</code> to render the following chart on the server. The output is
identical to what you'd get if you used <a href='https://gionkunz.github.io/chartist-js/'>chartist.js</a>
on the client, except that in this example, we're not executing any client-side code at all.
</p>
@Html.Raw(ViewData["ChartMarkup"])

View File

@@ -0,0 +1,34 @@
<h1>Image Resizing</h1>
<p>
This sample shows how the NPM module <a href="https://www.npmjs.com/package/sharp"><code>sharp</code></a>
can be used for dynamic image resizing from within an ASP.NET Core application. There is one copy of the
following image on disk, but we can set up an MVC action method that returns it resized to fit within an
arbitrary width and height.
</p>
<p>
<strong>Dependencies:</strong> On Windows and Linux, there are no native dependencies. Just running
<code>npm install</code> is enough. On OS X, however, you need to have <code>libvips</code> installed,
which you can get through <a href="http://brew.sh/">Homebrew</a> by running
<code>brew install homebrew/science/vips</code>.
</p>
<h3>100px wide [<a href="/resize/images/parrot.jpg?maxWidth=100">open</a>]</h3>
<img src="/resize/images/parrot.jpg?maxWidth=100" />
<h3>200px wide [<a href="/resize/images/parrot.jpg?maxWidth=200">open</a>]</h3>
<img src="/resize/images/parrot.jpg?maxWidth=200" />
<h3>400px wide [<a href="/resize/images/parrot.jpg?maxWidth=400">open</a>]</h3>
<img src="/resize/images/parrot.jpg?maxWidth=400" />
<h3>800px wide [<a href="/resize/images/parrot.jpg?maxWidth=800">open</a>]</h3>
<img src="/resize/images/parrot.jpg?maxWidth=800" />
<p>
<strong>Credit:</strong>
<em><a href="https://www.flickr.com/photos/dcoetzee/3572948635">Parrot</a>
by <a href="https://www.flickr.com/photos/dcoetzee/">D Coetzee</a>
is dedicated to the <a href="http://creativecommons.org/publicdomain/zero/1.0/">public domain (CC0)</a></em>
</p>

View File

@@ -7,6 +7,7 @@
</p>
<ul>
<li><a asp-action="ES2015Transpilation">ES2015 transpilation</a></li>
<li><a asp-action="Chart">Server-side chart rendering</a></li>
</ul>
<li><a asp-action="ES2015Transpilation">ES2015 transpilation</a>
<li><a asp-action="ImageResizing">Image resizing</a>
</li>

View File

@@ -1,9 +1,8 @@
<!doctype html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>NodeServices Examples</title>
<link rel="stylesheet" href="~/css/chartist.min.css" />
</head>
<body>
@RenderBody()

View File

@@ -4,6 +4,6 @@
"dependencies": {
"babel-core": "^6.7.4",
"babel-preset-es2015": "^6.6.0",
"node-chartist": "^1.0.2"
"sharp": "^0.15.0"
}
}

View File

@@ -0,0 +1,50 @@
{
"version": "1.0.0-*",
"tooling": {
"defaultNamespace": "NodeServicesExamples"
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"gcServer": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.AspNetCore.NodeServices": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"dnxcore50",
"portable-net45+win8"
]
}
},
"publishExclude": [
"node_modules",
"bower_components",
"**.xproj",
"**.user",
"**.vspscc"
],
"scripts": {
"prepublish": [ "npm install" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@@ -1,9 +1,6 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
yarn.lock
wwwroot/dist
# User-specific files
*.suo
*.user
@@ -43,6 +40,10 @@ TestResult.xml
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h

View File

@@ -38,8 +38,7 @@ namespace Webpack.ActionResults
request.GetEncodedUrl(),
request.Path + request.QueryString.Value,
_dataToSupply,
/* timeoutMilliseconds */ 30000,
/* requestPathBase */ "/"
/* timeoutMilliseconds */ 30000
);
response.ContentType = "text/html";

View File

@@ -0,0 +1,11 @@
FROM microsoft/aspnet:1.0.0-rc1-update1
RUN printf "deb http://ftp.us.debian.org/debian jessie main\n" >> /etc/apt/sources.list
RUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*
COPY . /app
WORKDIR /app
RUN ["dnu", "restore"]
EXPOSE 5000/tcp
ENTRYPOINT ["dnx", "-p", "project.json", "web"]

View File

@@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.SpaServices\Microsoft.AspNetCore.SpaServices.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="npm install" />
</Target>
</Project>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>a8905301-8492-42fd-9e83-f715a0fdc3a2</ProjectGuid>
<RootNamespace>Webpack</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\JavaScriptServices.sln\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>2018</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -11,10 +11,9 @@
"webpack-hot-middleware": "^2.7.1"
},
"dependencies": {
"aspnet-prerendering": "^1.0.4",
"aspnet-webpack": "^1.0.3",
"aspnet-prerendering": "^1.0.4",
"ts-loader": "^0.8.1",
"typescript": "^2.0.0",
"webpack": "^1.13.3"
"typescript": "^1.7.5"
}
}

View File

@@ -0,0 +1,52 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"gcServer": true
},
"tooling": {
"defaultNamespace": "Webpack"
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"dnxcore50",
"portable-net45+win8"
]
}
},
"publishOptions": {
"exclude": [
"node_modules",
"bower_components",
"**.xproj",
"**.user",
"**.vspscc"
]
},
"scripts": {
"prepublish": [ "npm install" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}

View File

@@ -2,10 +2,9 @@
"compilerOptions": {
"moduleResolution": "node",
"module": "commonjs",
"target": "es5",
"target": "es6",
"jsx": "preserve",
"sourceMap": true,
"lib": ["es6", "dom"]
"sourceMap": true
},
"exclude": [
"node_modules"

View File

@@ -10,6 +10,6 @@ module.exports = {
},
plugins: [
extractLESS,
new webpack.optimize.UglifyJsPlugin({ minimize: true, compressor: { warnings: false } })
new webpack.optimize.UglifyJsPlugin({ minimize: true })
]
};

View File

@@ -1,39 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="node_modules\**\*" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.ReactServices\Microsoft.AspNetCore.ReactServices.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SQLite" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="AutoMapper" Version="$(AutoMapperVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="npm install" />
<Exec Command="node node_modules/webpack/bin/webpack.js" />
</Target>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="$(AspNetCoreToolsVersion)" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>c870a92c-9e3f-4bf2-82b8-5758545a8b7c</ProjectGuid>
<RootNamespace>MusicStore</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\JavaScriptServices.sln\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>2018</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -1,4 +1,4 @@
import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer, Store as ReduxStore } from 'redux';
import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer } from 'redux';
import thunk from 'redux-thunk';
import { routerReducer } from 'react-router-redux';
import * as Store from './store';
@@ -16,7 +16,7 @@ export default function configureStore(initialState?: Store.ApplicationState) {
// Combine all reducers and instantiate the app-wide store instance
const allReducers = buildRootReducer(Store.reducers);
const store = createStoreWithMiddleware(allReducers, initialState) as ReduxStore<Store.ApplicationState>;
const store = createStoreWithMiddleware(allReducers, initialState) as Redux.Store<Store.ApplicationState>;
// Enable Webpack hot module replacement for reducers
if (module.hot) {

View File

@@ -2,7 +2,6 @@
"name": "music-store",
"version": "0.0.0",
"dependencies": {
"@types/history": "^2.0.0",
"@types/react": "^0.14.29",
"@types/react-bootstrap": "^0.0.35",
"@types/react-dom": "^0.14.14",
@@ -10,6 +9,7 @@
"@types/react-router": "^2.0.30",
"@types/react-router-bootstrap": "^0.0.27",
"@types/react-router-redux": "^4.0.30",
"@types/redux": "3.5.27",
"@types/redux-thunk": "^2.1.28",
"@types/source-map": "^0.1.28",
"@types/uglify-js": "^2.0.27",
@@ -42,7 +42,7 @@
"redux-typed": "^2.0.0",
"style-loader": "^0.13.0",
"ts-loader": "^0.8.1",
"typescript": "^2.0.3",
"typescript": "2.0.3",
"url-loader": "^0.5.7",
"webpack": "^1.13.2",
"webpack-hot-middleware": "^2.12.2",

View File

@@ -0,0 +1,83 @@
{
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.1",
"type": "platform"
},
"Microsoft.AspNetCore.ReactServices": "1.0.0-*",
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.1",
"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.1",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"AutoMapper": "5.0.2"
},
"tools": {
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true,
"compile": {
"exclude": ["node_modules"]
}
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {
"include": [
"appsettings.json",
"ClientApp/dist",
"node_modules",
"Views",
"web.config",
"wwwroot"
],
"exclude": [
"wwwroot/dist/*.map"
]
},
"scripts": {
"prepublish": [
"npm install",
"node node_modules/webpack/bin/webpack.js"
],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
},
"tooling": {
"defaultNamespace": "MusicStore"
}
}

View File

@@ -1,19 +1,11 @@
{
"compilerOptions": {
"baseUrl": ".",
"moduleResolution": "node",
"target": "es6",
"jsx": "preserve",
"sourceMap": true,
"experimentalDecorators": true,
"types": [ "webpack-env", "whatwg-fetch" ],
"paths": {
// Fix "Duplicate identifier" errors caused by multiple dependencies fetching their own copies of type definitions.
// We tell TypeScript which type definitions module to treat as the canonical one (instead of combining all of them).
"history": ["./node_modules/@types/history/index"],
"redux": ["./node_modules/@types/redux/index"],
"react": ["./node_modules/@types/react/index"]
}
"types": [ "webpack-env", "whatwg-fetch" ]
},
"exclude": [
"node_modules"

View File

@@ -10,7 +10,7 @@ module.exports = {
module: {
loaders: [
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'babel-loader' },
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'ts-loader?silent' },
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'ts-loader' },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }
]

View File

@@ -1,3 +1,4 @@
/node_modules/
project.lock.json
/wwwroot/dist/
/Properties/launchSettings.json

View File

@@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.ReactServices\Microsoft.AspNetCore.ReactServices.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<Exec Command="npm install" />
</Target>
</Project>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>abf90a5b-f4e0-438c-a6e4-9549fb43690b</ProjectGuid>
<RootNamespace>ReactGrid</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>2311</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,49 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"gcServer": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.AspNetCore.ReactServices": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"dnxcore50",
"portable-net45+win8"
]
}
},
"publishOptions": {
"exclude": [
"node_modules",
"bower_components",
"**.xproj",
"**.user",
"**.vspscc"
]
},
"scripts": {
"prepublish": [ "npm install" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}

View File

@@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Helpers for building Angular 2 applications on ASP.NET Core.</Description>
<TargetFrameworks>net451;netstandard1.6</TargetFrameworks>
<VersionPrefix>1.1.0</VersionPrefix>
<VersionSuffix>beta2</VersionSuffix>
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.SpaServices\Microsoft.AspNetCore.SpaServices.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="$(AspNetCoreVersion)" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<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)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>421807e6-b62c-417b-b901-46c5dedaa8f1</ProjectGuid>
<RootNamespace>Microsoft.AspNetCore.AngularServices</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]
[assembly: AssemblyCompany("Microsoft Corporation.")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]

View File

@@ -0,0 +1,3 @@
/node_modules/
/dist/
/bundles/

View File

@@ -0,0 +1,4 @@
/src/
/tsconfig.json
/build.js
/typings/

View File

@@ -0,0 +1,33 @@
// -------------
// No need to invoke this directly. To run a build, execute:
// npm run prepublish
// -------------
var Builder = require('systemjs-builder');
var builder = new Builder('./');
builder.config({
defaultJSExtensions: true,
paths: {
'angular2-aspnet': 'dist/Exports',
'angular2-aspnet/*': 'dist/*'
},
meta: {
'angular2/*': { build: false },
'rxjs/*': { build: false }
}
});
var entryPoint = 'dist/Exports';
var tasks = [
builder.bundle(entryPoint, './bundles/angular2-aspnet.js'),
builder.bundle(entryPoint, './bundles/angular2-aspnet.min.js', { minify: true })
];
Promise.all(tasks)
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.error('Build error');
console.error(err);
});

View File

@@ -0,0 +1,32 @@
{
"name": "angular2-aspnet",
"version": "0.0.6",
"description": "Helpers for Angular 2 apps built on ASP.NET",
"main": "./dist/Exports",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepublish": "rimraf *.d.ts dist/*.d.ts && tsc && node build.js"
},
"typings": "dist/Exports",
"author": "Microsoft",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/aspnet/JavaScriptServices/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/aspnet/JavaScriptServices.git"
},
"dependencies": {
"angular2": "2.0.0-beta.13",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.2"
},
"devDependencies": {
"es6-shim": "^0.35.0",
"rimraf": "^2.5.4",
"systemjs-builder": "^0.14.11",
"typescript": "^2.0.0",
"zone.js": "^0.6.10"
}
}

View File

@@ -0,0 +1,59 @@
If you just want to use this package, then you *don't have to build it*. Instead, just grab the prebuilt package from NPM:
npm install angular2-aspnet
The rest of this file is notes for anyone contributing to this package itself.
## How to build
Run the following:
npm install
npm run prepublish
Requirements:
* Node, NPM
* `tsc` installed globally (via `npm install -g typescript`)
## Project structure
This package is intended to be consumable both on the server in Node.js, and on the client. Also, it's written in TypeScript,
which neither of those environments knows natively, but the TypeScript type definitions need to get delivered with the package
so that developers get a good IDE experience when consuming it.
The build process is therefore:
1. Compile the TypeScript to produce the development-time (.d.ts) and server-side (.js) artifacts
`tsc` reads `tsconfig.json` and is instructed to compile all the `.ts` files in `src/`. It produces a corresponding
structure of `.js` and `.d.ts` files in `dist/`.
When a developer consumes the resulting package (via `npm install angular2-aspnet`),
- No additional copy of `angular2` will be installed, because this package's dependency on it is declared as a
`peerDependency`. This means it will work with whatever (compatible) version of `angular2` is already installed.
- At runtime inside Node.js, the `main` configuration in `package.json` means the developer can use a standard
`import` statement to consume this package (i.e., `import * from 'angular2-aspnet';` in either JS or TS files).
- At development time inside an IDE such as Visual Studio Code, the `typings` configuration in `package.json` means
the IDE will use the corresponding `.d.ts` file as type metadata for the variable imported that way.
2. Use the SystemJS builder to produce the client-side artifacts
`build.js` uses the SystemJS Builder API to combine files in `dist/` into `.js` files ready for use in client-side
SystemJS environments, and puts them in `bundles/`. The bundle files contain `System.register` calls so that any
other part of your client-side code that tries to import `angular2-aspnet` via SystemJS will get that module at runtime.
To make it work in an application:
- Set up some build step that copies your chosen bundle file from `bundles/` to some location where it will
be served to the client
- Below your `<script>` tag that loads SystemJS itself, and above the `<script>` tag that makes the first call to
`System.import`, have a `<script>` tag that loads the desired `angular2-aspnet.js` bundle file
For an example, see https://github.com/aspnet/NodeServices/tree/master/samples/angular/MusicStore
Of course, you can also bundle the `angular2-aspnet.js` file into a larger SystemJS bundle if you want to combine
it with the rest of the code in your application.
Currently, this build system does *not* attempt to send sourcemaps of the original TypeScript to the client. This
could be added if a strong need emerges.

View File

@@ -0,0 +1,59 @@
import { provide, Injectable, Provider } from 'angular2/core';
import { Connection, ConnectionBackend, Http, XHRBackend, RequestOptions, Request, RequestMethod, Response, ResponseOptions, ReadyState } from 'angular2/http';
@Injectable()
export class CachePrimedConnectionBackend extends ConnectionBackend {
private _preCachedResponses: PreCachedResponses;
constructor(private _underlyingBackend: ConnectionBackend, private _baseResponseOptions: ResponseOptions) {
super();
this._preCachedResponses = (<any>window).__preCachedResponses || {};
}
public createConnection(request: Request): Connection {
let cacheKey = request.url;
if (request.method === RequestMethod.Get && this._preCachedResponses.hasOwnProperty(cacheKey)) {
return new CacheHitConnection(request, this._preCachedResponses[cacheKey], this._baseResponseOptions);
} else {
return this._underlyingBackend.createConnection(request);
}
}
}
class CacheHitConnection implements Connection {
readyState: ReadyState;
request: Request;
response: any;
constructor (req: Request, cachedResponse: PreCachedResponse, baseResponseOptions: ResponseOptions) {
this.request = req;
this.readyState = ReadyState.Done;
// Workaround for difficulty consuming CommonJS default exports in TypeScript. Note that it has to be a dynamic
// 'require', and not an 'import' statement, because the module isn't available on the server.
let obsCtor: any = require('rxjs/Observable').Observable;
this.response = new obsCtor(responseObserver => {
let response = new Response(new ResponseOptions({ body: cachedResponse.body, status: cachedResponse.statusCode }));
responseObserver.next(response);
responseObserver.complete();
});
}
}
declare var require: any; // Part of the workaround mentioned below. Can remove this after updating Angular.
interface PreCachedResponses {
[url: string]: PreCachedResponse;
}
interface PreCachedResponse {
statusCode: number;
body: string;
}
export const CACHE_PRIMED_HTTP_PROVIDERS = [
provide(Http, {
useFactory: (xhrBackend, requestOptions, responseOptions) => new Http(new CachePrimedConnectionBackend(xhrBackend, responseOptions), requestOptions),
deps: [XHRBackend, RequestOptions, ResponseOptions]
}),
];

View File

@@ -0,0 +1,2 @@
export * from './CachePrimedHttp';
export * from './Validation';

View File

@@ -0,0 +1,34 @@
import { ControlGroup } from 'angular2/common';
import { Response } from 'angular2/http';
export class Validation {
public static showValidationErrors(response: ValidationErrorResult | Response, controlGroup: ControlGroup): void {
if (response instanceof Response) {
var httpResponse = <Response>response;
response = <ValidationErrorResult>(httpResponse.json());
}
// It's not yet clear whether this is a legitimate and supported use of the ng.ControlGroup API.
// Need feedback from the Angular 2 team on whether there's a better way.
var errors = <ValidationErrorResult>response;
Object.keys(errors || {}).forEach(key => {
errors[key].forEach(errorMessage => {
// If there's a specific control for this key, then use it. Otherwise associate the error
// with the whole control group.
var control = controlGroup.controls[key] || controlGroup;
// This is rough. Need to find out if there's a better way, or if this is even supported.
if (!control.errors) {
(<any>control)._errors = {};
}
control.errors[errorMessage] = true;
});
});
}
}
export interface ValidationErrorResult {
[propertyName: string]: string[];
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": false,
"declaration": true,
"experimentalDecorators": true,
"noLib": false,
"outDir": "./dist",
"lib": ["es2015", "dom"]
},
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,28 @@
{
"description": "Helpers for building Angular 2 applications on ASP.NET Core.",
"version": "1.0.0-*",
"packOptions": {
"repository": {
"type": "git",
"url": "git://github.com/aspnet/javascriptservices"
},
"tags": [
"aspnetcore",
"aspnetcoremvc",
"nodeservices"
]
},
"buildOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk",
"xmlDoc": true
},
"dependencies": {
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
},
"frameworks": {
"net451": {},
"netstandard1.6": {}
}
}

View File

@@ -1,3 +0,0 @@
/bin/
/node_modules/
yarn.lock

View File

@@ -1,36 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Socket-based RPC for Microsoft.AspNetCore.NodeServices.</Description>
<TargetFrameworks>net451;netstandard1.6</TargetFrameworks>
<VersionPrefix>1.1.0</VersionPrefix>
<VersionSuffix>beta2</VersionSuffix>
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Content\**\*" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<PackageReference Include="Microsoft.Tpl.Dataflow" Version="$(MicrosoftDataflowVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<PackageReference Include="System.IO.Pipes" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(ThreadingDataflowVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
<Exec Command="npm install" />
<Exec Command="node node_modules/webpack/bin/webpack.js" />
</Target>
</Project>

View File

@@ -1,21 +0,0 @@
using System;
namespace Microsoft.AspNetCore.NodeServices.Sockets
{
/// <summary>
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
/// </summary>
public static class NodeServicesOptionsExtensions
{
/// <summary>
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
/// Node.js instances and perform RPC calls over binary sockets (on Windows, this is
/// implemented as named pipes; on other platforms it uses domain sockets).
/// </summary>
public static void UseSocketHosting(this NodeServicesOptions options)
{
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
options.NodeInstanceFactory = () => new SocketNodeInstance(options, pipeName);
}
}
}

View File

@@ -1,11 +0,0 @@
{
"compilerOptions": {
"target": "es3",
"module": "commonjs",
"moduleResolution": "node",
"types": ["node"]
},
"exclude": [
"node_modules"
]
}

View File

@@ -1,18 +0,0 @@
{
"name": "nodeservices.sockets",
"version": "1.0.0",
"description": "This is not really an NPM package and will not be published. This file exists only to reference compilation tools.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "./node_modules/.bin/webpack"
},
"author": "Microsoft",
"license": "Apache-2.0",
"devDependencies": {
"@types/node": "^6.0.42",
"ts-loader": "^0.8.2",
"typescript": "^2.0.0",
"webpack": "^1.13.1"
}
}

View File

@@ -1,20 +0,0 @@
module.exports = {
target: 'node',
externals: ['fs', 'net', 'events', 'readline', 'stream'],
resolve: {
extensions: [ '.ts' ]
},
module: {
loaders: [
{ test: /\.ts$/, loader: 'ts-loader' },
]
},
entry: {
'entrypoint-socket': ['./TypeScript/SocketNodeInstanceEntryPoint'],
},
output: {
libraryTarget: 'commonjs',
path: './Content/Node',
filename: '[name].js'
}
};

View File

@@ -1,3 +1,2 @@
/bin/
/node_modules/
yarn.lock

View File

@@ -0,0 +1,18 @@
namespace Microsoft.AspNetCore.NodeServices
{
/// <summary>
/// Represents a way of creating and invoking code in a Node.js environment.
/// </summary>
public enum NodeHostingModel
{
/// <summary>
/// An out-of-process Node.js instance where RPC calls are made via HTTP.
/// </summary>
Http,
/// <summary>
/// An out-of-process Node.js instance where RPC calls are made over binary sockets.
/// </summary>
Socket,
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.AspNetCore.NodeServices.HostingModels;
namespace Microsoft.AspNetCore.NodeServices
{
@@ -19,7 +20,32 @@ namespace Microsoft.AspNetCore.NodeServices
throw new ArgumentNullException(nameof (options));
}
return new NodeServicesImpl(options.NodeInstanceFactory);
return new NodeServicesImpl(() => CreateNodeInstance(options));
}
private static INodeInstance CreateNodeInstance(NodeServicesOptions options)
{
if (options.NodeInstanceFactory != null)
{
// If you've explicitly supplied an INodeInstance factory, we'll use that. This is useful for
// custom INodeInstance implementations.
return options.NodeInstanceFactory();
}
else
{
switch (options.HostingModel)
{
case NodeHostingModel.Http:
return new HttpNodeInstance(options.ProjectPath, options.WatchFileExtensions, options.NodeInstanceOutputLogger,
options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort, /* port */ 0);
case NodeHostingModel.Socket:
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
return new SocketNodeInstance(options.ProjectPath, options.WatchFileExtensions, pipeName, options.NodeInstanceOutputLogger,
options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort);
default:
throw new ArgumentException("Unknown hosting model: " + options.HostingModel);
}
}
}
}
}

View File

@@ -13,6 +13,11 @@ namespace Microsoft.AspNetCore.NodeServices
/// </summary>
public class NodeServicesOptions
{
/// <summary>
/// Defines the default <see cref="NodeHostingModel"/>.
/// </summary>
public const NodeHostingModel DefaultNodeHostingModel = NodeHostingModel.Http;
internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds);
private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000;
private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices";
@@ -31,6 +36,7 @@ namespace Microsoft.AspNetCore.NodeServices
EnvironmentVariables = new Dictionary<string, string>();
InvocationTimeoutMilliseconds = DefaultInvocationTimeoutMilliseconds;
HostingModel = DefaultNodeHostingModel;
WatchFileExtensions = (string[])DefaultWatchFileExtensions.Clone();
// In an ASP.NET environment, we can use the IHostingEnvironment data to auto-populate a few
@@ -47,15 +53,15 @@ namespace Microsoft.AspNetCore.NodeServices
NodeInstanceOutputLogger = loggerFactory != null
? loggerFactory.CreateLogger(LogCategoryName)
: new ConsoleLogger(LogCategoryName, null, false);
// By default, we use this package's built-in out-of-process-via-HTTP hosting/transport
this.UseHttpHosting();
}
/// <summary>
/// Specifies how to construct Node.js instances. An <see cref="INodeInstance"/> encapsulates all details about
/// how Node.js instances are launched and communicated with. A new <see cref="INodeInstance"/> will be created
/// automatically if the previous instance has terminated (e.g., because a source file changed).
/// Specifies which <see cref="NodeHostingModel"/> should be used.
/// </summary>
public NodeHostingModel HostingModel { get; set; }
/// <summary>
/// If set, this callback function will be invoked to supply the <see cref="INodeServices"/> instance.
/// </summary>
public Func<INodeInstance> NodeInstanceFactory { get; set; }

View File

@@ -125,7 +125,7 @@
// Signal to the NodeServices base class that we're ready to accept invocations
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
});
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid), /* ignoreSigint */ true);
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
function readRequestBodyAsJson(request, callback) {
var requestBodyAsString = '';
request.on('data', function (chunk) { requestBodyAsString += chunk; });
@@ -255,7 +255,7 @@
*/
"use strict";
var pollIntervalMs = 1000;
function exitWhenParentExits(parentPid, ignoreSigint) {
function exitWhenParentExits(parentPid) {
setInterval(function () {
if (!processExists(parentPid)) {
// Can't log anything at this point, because out stdout was connected to the parent,
@@ -263,24 +263,6 @@
process.exit();
}
}, pollIntervalMs);
if (ignoreSigint) {
// Pressing ctrl+c in the terminal sends a SIGINT to all processes in the foreground process tree.
// By default, the Node process would then exit before the .NET process, because ASP.NET implements
// a delayed shutdown to allow ongoing requests to complete.
//
// This is problematic, because if Node exits first, the CopyToAsync code in ConditionalProxyMiddleware
// will experience a read fault, and logs a huge load of errors. Fortunately, since the Node process is
// already set up to shut itself down if it detects the .NET process is terminated, all we have to do is
// ignore the SIGINT. The Node process will then terminate automatically after the .NET process does.
//
// A better solution would be to have WebpackDevMiddleware listen for SIGINT and gracefully close any
// ongoing EventSource connections before letting the Node process exit, independently of the .NET
// process exiting. However, doing this well in general is very nontrivial (see all the discussion at
// https://github.com/nodejs/node/issues/2642).
process.on('SIGINT', function () {
console.log('Received SIGINT. Waiting for .NET process to exit...');
});
}
}
exports.exitWhenParentExits = exitWhenParentExits;
function processExists(pid) {

View File

@@ -44,81 +44,11 @@
/* 0 */
/***/ function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1);
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
// but simplifies things for the consumer of this module.
__webpack_require__(2);
var net = __webpack_require__(3);
var path = __webpack_require__(4);
var readline = __webpack_require__(5);
var ArgsUtil_1 = __webpack_require__(6);
var ExitWhenParentExits_1 = __webpack_require__(7);
var virtualConnectionServer = __webpack_require__(8);
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
// reference to Node's runtime 'require' function.
var dynamicRequire = eval('require');
// Signal to the .NET side when we're ready to accept invocations
var server = net.createServer().on('listening', function () {
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
});
// Each virtual connection represents a separate invocation
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
readline.createInterface(connection, null).on('line', function (line) {
try {
// Get a reference to the function to invoke
var invocation = JSON.parse(line);
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
// Prepare a callback for accepting non-streamed JSON responses
var hasInvokedCallback_1 = false;
var invocationCallback = function (errorValue, successValue) {
if (hasInvokedCallback_1) {
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
+ ' or the result stream has already been accessed');
}
hasInvokedCallback_1 = true;
connection.end(JSON.stringify({
result: successValue,
errorMessage: errorValue && (errorValue.message || errorValue),
errorDetails: errorValue && (errorValue.stack || null)
}));
};
// Also support streamed binary responses
Object.defineProperty(invocationCallback, 'stream', {
enumerable: true,
get: function () {
hasInvokedCallback_1 = true;
return connection;
}
});
// Actually invoke it, passing through any supplied args
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
}
catch (ex) {
connection.end(JSON.stringify({
errorMessage: ex.message,
errorDetails: ex.stack
}));
}
});
});
// Begin listening now. The underlying transport varies according to the runtime platform.
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
var useWindowsNamedPipes = /^win/.test(process.platform);
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
server.listen(listenAddress);
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
module.exports = __webpack_require__(7);
/***/ },
/* 1 */,
/* 2 */
/***/ function(module, exports) {
@@ -160,12 +90,7 @@
/***/ },
/* 3 */
/***/ function(module, exports) {
module.exports = require("net");
/***/ },
/* 3 */,
/* 4 */
/***/ function(module, exports) {
@@ -173,12 +98,6 @@
/***/ },
/* 5 */
/***/ function(module, exports) {
module.exports = require("readline");
/***/ },
/* 6 */
/***/ function(module, exports) {
"use strict";
@@ -204,7 +123,7 @@
/***/ },
/* 7 */
/* 6 */
/***/ function(module, exports) {
/*
@@ -271,12 +190,95 @@
/***/ },
/* 8 */
/* 7 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var events_1 = __webpack_require__(9);
var VirtualConnection_1 = __webpack_require__(10);
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
// but simplifies things for the consumer of this module.
__webpack_require__(2);
var net = __webpack_require__(8);
var path = __webpack_require__(4);
var readline = __webpack_require__(9);
var ArgsUtil_1 = __webpack_require__(5);
var ExitWhenParentExits_1 = __webpack_require__(6);
var virtualConnectionServer = __webpack_require__(10);
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
// reference to Node's runtime 'require' function.
var dynamicRequire = eval('require');
// Signal to the .NET side when we're ready to accept invocations
var server = net.createServer().on('listening', function () {
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
});
// Each virtual connection represents a separate invocation
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
readline.createInterface(connection, null).on('line', function (line) {
try {
// Get a reference to the function to invoke
var invocation = JSON.parse(line);
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
// Prepare a callback for accepting non-streamed JSON responses
var hasInvokedCallback_1 = false;
var invocationCallback = function (errorValue, successValue) {
if (hasInvokedCallback_1) {
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
+ ' or the result stream has already been accessed');
}
hasInvokedCallback_1 = true;
connection.end(JSON.stringify({
result: successValue,
errorMessage: errorValue && (errorValue.message || errorValue),
errorDetails: errorValue && (errorValue.stack || null)
}));
};
// Also support streamed binary responses
Object.defineProperty(invocationCallback, 'stream', {
enumerable: true,
get: function () {
hasInvokedCallback_1 = true;
return connection;
}
});
// Actually invoke it, passing through any supplied args
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
}
catch (ex) {
connection.end(JSON.stringify({
errorMessage: ex.message,
errorDetails: ex.stack
}));
}
});
});
// Begin listening now. The underlying transport varies according to the runtime platform.
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
var useWindowsNamedPipes = /^win/.test(process.platform);
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
server.listen(listenAddress);
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
/***/ },
/* 8 */
/***/ function(module, exports) {
module.exports = require("net");
/***/ },
/* 9 */
/***/ function(module, exports) {
module.exports = require("readline");
/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var events_1 = __webpack_require__(11);
var VirtualConnection_1 = __webpack_require__(12);
// Keep this in sync with the equivalent constant in the .NET code. Both sides split up their transmissions into frames with this max length,
// and both will reject longer frames.
var MaxFrameBodyLength = 16 * 1024;
@@ -458,13 +460,13 @@
/***/ },
/* 9 */
/* 11 */
/***/ function(module, exports) {
module.exports = require("events");
/***/ },
/* 10 */
/* 12 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
@@ -473,18 +475,17 @@
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var stream_1 = __webpack_require__(11);
var stream_1 = __webpack_require__(13);
/**
* Represents a virtual connection. Multiple virtual connections may be multiplexed over a single physical socket connection.
*/
var VirtualConnection = (function (_super) {
__extends(VirtualConnection, _super);
function VirtualConnection(_beginWriteCallback) {
var _this = _super.call(this) || this;
_this._beginWriteCallback = _beginWriteCallback;
_this._flowing = false;
_this._receivedDataQueue = [];
return _this;
_super.call(this);
this._beginWriteCallback = _beginWriteCallback;
this._flowing = false;
this._receivedDataQueue = [];
}
VirtualConnection.prototype._read = function () {
this._flowing = true;
@@ -515,7 +516,7 @@
/***/ },
/* 11 */
/* 13 */
/***/ function(module, exports) {
module.exports = require("stream");

View File

@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
@@ -34,19 +36,21 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
private bool _disposed;
private int _portNumber;
public HttpNodeInstance(NodeServicesOptions options, int port = 0)
public HttpNodeInstance(string projectPath, string[] watchFileExtensions, ILogger nodeInstanceOutputLogger,
IDictionary<string, string> environmentVars, int invocationTimeoutMilliseconds, bool launchWithDebugging,
int debuggingPort, int port = 0)
: base(
EmbeddedResourceReader.Read(
typeof(HttpNodeInstance),
"/Content/Node/entrypoint-http.js"),
options.ProjectPath,
options.WatchFileExtensions,
projectPath,
watchFileExtensions,
MakeCommandLineOptions(port),
options.NodeInstanceOutputLogger,
options.EnvironmentVariables,
options.InvocationTimeoutMilliseconds,
options.LaunchWithDebugging,
options.DebuggingPort)
nodeInstanceOutputLogger,
environmentVars,
invocationTimeoutMilliseconds,
launchWithDebugging,
debuggingPort)
{
_client = new HttpClient();
}
@@ -91,7 +95,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
case "application/octet-stream":
// Streamed responses have to be received as System.IO.Stream instances
if (typeof(T) != typeof(Stream) && typeof(T) != typeof(object))
if (typeof(T) != typeof(Stream))
{
throw new ArgumentException(
"Node module responded with binary stream. This cannot be converted to the requested generic type: " +

View File

@@ -13,13 +13,6 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
/// </summary>
public bool NodeInstanceUnavailable { get; private set; }
/// <summary>
/// If true, indicates that even though the invocation failed because the Node.js instance could not be reached
/// or needs to be restarted, that Node.js instance may remain alive for a period in order to complete any
/// outstanding requests.
/// </summary>
public bool AllowConnectionDraining { get; private set;}
/// <summary>
/// Creates a new instance of <see cref="NodeInvocationException"/>.
/// </summary>
@@ -36,20 +29,10 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
/// <param name="message">A description of the exception.</param>
/// <param name="details">Additional information, such as a Node.js stack trace, representing the exception.</param>
/// <param name="nodeInstanceUnavailable">Specifies a value for the <see cref="NodeInstanceUnavailable"/> flag.</param>
/// <param name="allowConnectionDraining">Specifies a value for the <see cref="AllowConnectionDraining"/> flag.</param>
public NodeInvocationException(string message, string details, bool nodeInstanceUnavailable, bool allowConnectionDraining)
public NodeInvocationException(string message, string details, bool nodeInstanceUnavailable)
: this(message, details)
{
// Reject a meaningless combination of flags
if (allowConnectionDraining && !nodeInstanceUnavailable)
{
throw new ArgumentException(
$"The '${ nameof(allowConnectionDraining) }' parameter cannot be true " +
$"unless the '${ nameof(nodeInstanceUnavailable) }' parameter is also true.");
}
NodeInstanceUnavailable = nodeInstanceUnavailable;
AllowConnectionDraining = allowConnectionDraining;
}
}
}

View File

@@ -1,17 +0,0 @@
namespace Microsoft.AspNetCore.NodeServices.HostingModels
{
/// <summary>
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
/// </summary>
public static class NodeServicesOptionsExtensions
{
/// <summary>
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
/// Node.js instances and perform RPC calls over HTTP.
/// </summary>
public static void UseHttpHosting(this NodeServicesOptions options)
{
options.NodeInstanceFactory = () => new HttpNodeInstance(options);
}
}
}

View File

@@ -27,12 +27,21 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
protected readonly ILogger OutputLogger;
private const string ConnectionEstablishedMessage = "[Microsoft.AspNetCore.NodeServices:Listening]";
private const string DebuggingStartedMessageFormat = @"-----
*** Node.js debugging is enabled ***
{0}
To debug, run:
node-inspector{1}
If you haven't yet installed node-inspector, you can do so as follows:
npm install -g node-inspector
-----";
private readonly TaskCompletionSource<object> _connectionIsReadySource = new TaskCompletionSource<object>();
private bool _disposed;
private readonly StringAsTempFile _entryPointScript;
private FileSystemWatcher _fileSystemWatcher;
private int _invocationTimeoutMilliseconds;
private bool _launchWithDebugging;
private readonly Process _nodeProcess;
private int? _nodeDebuggingPort;
private bool _nodeProcessNeedsRestart;
@@ -69,10 +78,9 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
OutputLogger = nodeOutputLogger;
_entryPointScript = new StringAsTempFile(entryPointScript);
_invocationTimeoutMilliseconds = invocationTimeoutMilliseconds;
_launchWithDebugging = launchWithDebugging;
var startInfo = PrepareNodeProcessStartInfo(_entryPointScript.FileName, projectPath, commandLineArguments,
environmentVars, _launchWithDebugging, debuggingPort);
environmentVars, launchWithDebugging, debuggingPort);
_nodeProcess = LaunchNodeProcess(startInfo);
_watchFileExtensions = watchFileExtensions;
_fileSystemWatcher = BeginFileWatcher(projectPath);
@@ -95,17 +103,10 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
{
// This special kind of exception triggers a transparent retry - NodeServicesImpl will launch
// a new Node instance and pass the invocation to that one instead.
// Note that if the Node process is listening for debugger connections, then we need it to shut
// down immediately and not stay open for connection draining (because if it did, the new Node
// instance wouldn't able to start, because the old one would still hold the debugging port).
var message = _nodeProcess.HasExited
? "The Node process has exited"
: "The Node process needs to restart";
throw new NodeInvocationException(
message,
details: null,
nodeInstanceUnavailable: true,
allowConnectionDraining: !_launchWithDebugging);
throw new NodeInvocationException(message, null, nodeInstanceUnavailable: true);
}
// Construct a new cancellation token that combines the supplied token with the configured invocation
@@ -205,8 +206,8 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
/// <param name="projectPath">The root path of the project. This is used when locating Node.js modules relative to the project root.</param>
/// <param name="commandLineArguments">Command-line arguments to be passed to the Node.js process.</param>
/// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
/// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 Inspector connections.</param>
/// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 Inspector connections on this port.</param>
/// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 debugger connections.</param>
/// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port.</param>
/// <returns></returns>
protected virtual ProcessStartInfo PrepareNodeProcessStartInfo(
string entryPointFilename, string projectPath, string commandLineArguments,
@@ -216,7 +217,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
string debuggingArgs;
if (launchWithDebugging)
{
debuggingArgs = debuggingPort != default(int) ? $"--inspect={debuggingPort} " : "--inspect ";
debuggingArgs = debuggingPort != default(int) ? $"--debug={debuggingPort} " : "--debug ";
_nodeDebuggingPort = debuggingPort;
}
else
@@ -324,26 +325,17 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
private static Process LaunchNodeProcess(ProcessStartInfo startInfo)
{
try {
var process = Process.Start(startInfo);
var process = Process.Start(startInfo);
// On Mac at least, a killed child process is left open as a zombie until the parent
// captures its exit code. We don't need the exit code for this process, and don't want
// to use process.WaitForExit() explicitly (we'd have to block the thread until it really
// has exited), but we don't want to leave zombies lying around either. It's sufficient
// to use process.EnableRaisingEvents so that .NET will grab the exit code and let the
// zombie be cleaned away without having to block our thread.
process.EnableRaisingEvents = true;
// On Mac at least, a killed child process is left open as a zombie until the parent
// captures its exit code. We don't need the exit code for this process, and don't want
// to use process.WaitForExit() explicitly (we'd have to block the thread until it really
// has exited), but we don't want to leave zombies lying around either. It's sufficient
// to use process.EnableRaisingEvents so that .NET will grab the exit code and let the
// zombie be cleaned away without having to block our thread.
process.EnableRaisingEvents = true;
return process;
} catch (Exception ex) {
var message = "Failed to start Node process. To resolve this:.\n\n"
+ "[1] Ensure that Node.js is installed and can be found in one of the PATH directories.\n"
+ $" Current PATH enviroment variable is: { Environment.GetEnvironmentVariable("PATH") }\n"
+ " Make sure the Node executable is in one of those directories, or update your PATH.\n\n"
+ "[2] See the InnerException for further details of the cause.";
throw new InvalidOperationException(message, ex);
}
return process;
}
private static string UnencodeNewlines(string str)
@@ -379,9 +371,10 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
{
if (evt.Data != null)
{
if (_launchWithDebugging && IsDebuggerMessage(evt.Data))
if (IsDebuggerListeningMessage(evt.Data))
{
OutputLogger.LogWarning(evt.Data);
var debugPortArg = _nodeDebuggingPort.HasValue ? $" --debug-port={_nodeDebuggingPort.Value}" : string.Empty;
OutputLogger.LogWarning(string.Format(DebuggingStartedMessageFormat, evt.Data, debugPortArg));
}
else if (!initializationIsCompleted)
{
@@ -400,12 +393,9 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
_nodeProcess.BeginErrorReadLine();
}
private static bool IsDebuggerMessage(string message)
private static bool IsDebuggerListeningMessage(string message)
{
return message.StartsWith("Debugger attached", StringComparison.OrdinalIgnoreCase) ||
message.StartsWith("Debugger listening ", StringComparison.OrdinalIgnoreCase) ||
message.StartsWith("To start debugging", StringComparison.OrdinalIgnoreCase) ||
message.Contains("chrome-devtools:");
return message.StartsWith("Debugger listening ", StringComparison.OrdinalIgnoreCase);
}
private FileSystemWatcher BeginFileWatcher(string rootDir)

View File

@@ -2,7 +2,7 @@ using System.IO;
using System.IO.Pipes;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
{
internal class NamedPipeConnection : StreamConnection
{

View File

@@ -2,7 +2,7 @@ using System;
using System.IO;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
{
internal abstract class StreamConnection : IDisposable
{

View File

@@ -2,7 +2,7 @@ using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
{
internal class UnixDomainSocketConnection : StreamConnection
{

View File

@@ -3,7 +3,7 @@ using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
{
// From System.IO.Pipes/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs (an internal class in System.IO.Pipes)
internal sealed class UnixDomainSocketEndPoint : EndPoint

View File

@@ -1,15 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.NodeServices.HostingModels;
using Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections;
using Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections;
using Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections;
using Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.NodeServices.Sockets
namespace Microsoft.AspNetCore.NodeServices.HostingModels
{
/// <summary>
/// A specialisation of the OutOfProcessNodeInstance base class that uses a lightweight binary streaming protocol
@@ -41,19 +42,21 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
private string _socketAddress;
private VirtualConnectionClient _virtualConnectionClient;
public SocketNodeInstance(NodeServicesOptions options, string socketAddress)
public SocketNodeInstance(string projectPath, string[] watchFileExtensions, string socketAddress,
ILogger nodeInstanceOutputLogger, IDictionary<string, string> environmentVars,
int invocationTimeoutMilliseconds, bool launchWithDebugging, int debuggingPort)
: base(
EmbeddedResourceReader.Read(
typeof(SocketNodeInstance),
"/Content/Node/entrypoint-socket.js"),
options.ProjectPath,
options.WatchFileExtensions,
projectPath,
watchFileExtensions,
MakeNewCommandLineOptions(socketAddress),
options.NodeInstanceOutputLogger,
options.EnvironmentVariables,
options.InvocationTimeoutMilliseconds,
options.LaunchWithDebugging,
options.DebuggingPort)
nodeInstanceOutputLogger,
environmentVars,
invocationTimeoutMilliseconds,
launchWithDebugging,
debuggingPort)
{
_socketAddress = socketAddress;
}
@@ -62,15 +65,11 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
{
if (_connectionHasFailed)
{
// _connectionHasFailed implies a protocol-level error. The old instance is no longer of any use.
var allowConnectionDraining = false;
// This special exception type forces NodeServicesImpl to restart the Node instance
throw new NodeInvocationException(
"The SocketNodeInstance socket connection failed. See logs to identify the reason.",
details: null,
nodeInstanceUnavailable: true,
allowConnectionDraining: allowConnectionDraining);
null,
nodeInstanceUnavailable: true);
}
if (_virtualConnectionClient == null)
@@ -80,7 +79,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
// wait for the same connection task. There's no reason why the first caller should have the
// special ability to cancel the connection process in a way that would affect subsequent
// callers. So, each caller just independently stops awaiting connection if that call is cancelled.
await ThrowOnCancellation(EnsureVirtualConnectionClientCreated(), cancellationToken);
await EnsureVirtualConnectionClientCreated().OrThrowOnCancellation(cancellationToken);
}
// For each invocation, we open a new virtual connection. This gives an API equivalent to opening a new
@@ -179,7 +178,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
using (var jsonWriter = new JsonTextWriter(streamWriter))
{
jsonWriter.CloseOutput = false;
jsonWriter.AutoCompleteOnClose = false;
var serializer = JsonSerializer.Create(jsonSerializerSettings);
serializer.Serialize(jsonWriter, serializableObject);
@@ -217,17 +215,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
return $"--listenAddress {listenAddress}";
}
private static Task ThrowOnCancellation(Task task, CancellationToken cancellationToken)
{
return task.IsCompleted
? task // If the task is already completed, no need to wrap it in a further layer of task
: task.ContinueWith(
_ => {}, // If the task completes, allow execution to continue
cancellationToken,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
#pragma warning disable 649 // These properties are populated via JSON deserialization
private class RpcJsonResponse<TResult>
{

View File

@@ -4,7 +4,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections
{
/// <summary>
/// A virtual read/write connection, typically to a remote process. Multiple virtual connections can be

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections
{
/// <summary>
/// A callback that will be invoked if the <see cref="VirtualConnectionClient"/> encounters a read error.

View File

@@ -1,35 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Invoke Node.js modules at runtime in ASP.NET Core applications.</Description>
<TargetFrameworks>net451;netstandard1.6</TargetFrameworks>
<VersionPrefix>1.1.1</VersionPrefix>
<VersionSuffix>alpha</VersionSuffix>
<PackageTags>aspnetcore;aspnetcoremvc;nodeservices</PackageTags>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Content\**\*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<PackageReference Include="System.Diagnostics.Process" Version="$(CoreFxVersion)" />
<PackageReference Include="System.IO.FileSystem.Watcher" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Runtime.Loader" Version="$(CoreFxVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
<Exec Command="npm install" />
<Exec Command="node node_modules/webpack/bin/webpack.js" />
</Target>
</Project>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<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)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>b0fa4175-8b29-4904-9780-28b3c24b0567</ProjectGuid>
<RootNamespace>Microsoft.AspNetCore.NodeServices</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\JavaScriptServices.sln\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices
return InvokeExportWithPossibleRetryAsync<T>(moduleName, exportedFunctionName, args, /* allowRetry */ true, cancellationToken);
}
private async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
public async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
{
ThrowAnyOutstandingDelayedDisposalException();
var nodeInstance = GetOrCreateCurrentNodeInstance();
@@ -72,8 +72,7 @@ namespace Microsoft.AspNetCore.NodeServices
{
if (_currentNodeInstance == nodeInstance)
{
var disposalDelay = ex.AllowConnectionDraining ? ConnectionDrainingTimespan : TimeSpan.Zero;
DisposeNodeInstance(_currentNodeInstance, disposalDelay);
DisposeNodeInstance(_currentNodeInstance, delay: ConnectionDrainingTimespan);
_currentNodeInstance = null;
}
}

View File

@@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]
[assembly: AssemblyCompany("Microsoft Corporation.")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]

View File

@@ -67,7 +67,7 @@ public async Task<IActionResult> MyAction([FromServices] INodeServices nodeServi
}
```
Of course, you also need to supply the Node.js code you want to invoke. Create a file called `addNumbers.js` at the root of your ASP.NET Core application, and add the following code:
Of course, you also need to supply the Node.js code you want to invoke. Create a file called `addNumber.js` at the root of your ASP.NET Core application, and add the following code:
```javascript
module.exports = function (callback, first, second) {
@@ -333,23 +333,25 @@ People have asked about using [VroomJS](https://github.com/fogzot/vroomjs) as a
### Built-in hosting models
Normally, you can just use the default hosting model, and not worry about it. But if you have some special requirements, you can write your own hosting model, or reference a package that supplies one.
For example, you could use the 'socket' hosting model. It performs RPC between .NET and Node.js using a fast, low-level binary channel rather than the default HTTP transport. To do this, first install the NuGet package `Microsoft.AspNetCore.NodeServices.Sockets`. Then, at the top of your `Startup.cs` file, add:
Normally, you can just use the default hosting model, and not worry about it. But if you have some special requirements, select a hosting model by setting the `HostingModel` property on the `options` object in `AddNodeServices`. Example:
```csharp
using Microsoft.AspNetCore.NodeServices.Sockets;
```
...then in your `Startup.cs` file's `ConfigureServices` method, you can configure:
```csharp
services.AddNodeServices(options => {
options.UseSocketHosting();
services.AddNodeServices(options =>
{
options.HostingModel = NodeHostingModel.Socket;
});
```
Now when you run your application, it will use the socket-based hosting and transport mechanism. In the past, the socket transport was faster than HTTP, but since .NET Core 1.1 improved the performance of `HttpClient` there isn't really any speed difference any more, so there's no longer any significant advantage to using `Microsoft.AspNetCore.NodeServices.Sockets`.
**Available hosting models**
* `Socket`
* Launches Node as a separate process, and communicates with it using named pipes (on Windows) or domain sockets (on Linux / OS X).
* This is faster than `Http` because it uses a low-level binary protocol with very low overhead. It retains one continuous connection for the whole lifetime of the Node instance, so it doesn't have to keep waiting for new connections to open.
* `Http` (default)
* Launches Node as a separate process, and communicates with it by making HTTP requests.
* This primarily exists because it was implemented before `Socket`, but there's no particular reason to use it now that `Socket` is available. It could theoretically be useful if you wanted to run Node instances on separate servers (though there isn't currently any built-in API for configuring that).
The default transport may change from `Http` to `Socket` in the near future, because it's faster.
### Custom hosting models

View File

@@ -76,7 +76,7 @@ server.listen(requestedPortOrZero, 'localhost', function () {
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
});
exitWhenParentExits(parseInt(parsedArgs.parentPid), /* ignoreSigint */ true);
exitWhenParentExits(parseInt(parsedArgs.parentPid));
function readRequestBodyAsJson(request, callback) {
let requestBodyAsString = '';

View File

@@ -1,12 +1,12 @@
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
// but simplifies things for the consumer of this module.
import '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/OverrideStdOutputs';
import './Util/OverrideStdOutputs';
import * as net from 'net';
import * as path from 'path';
import * as readline from 'readline';
import { Duplex } from 'stream';
import { parseArgs } from '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/ArgsUtil';
import { exitWhenParentExits } from '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/ExitWhenParentExits';
import { parseArgs } from './Util/ArgsUtil';
import { exitWhenParentExits } from './Util/ExitWhenParentExits';
import * as virtualConnectionServer from './VirtualConnections/VirtualConnectionServer';
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
@@ -70,7 +70,7 @@ const parsedArgs = parseArgs(process.argv);
const listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
server.listen(listenAddress);
exitWhenParentExits(parseInt(parsedArgs.parentPid), /* ignoreSigint */ true);
exitWhenParentExits(parseInt(parsedArgs.parentPid));
interface RpcInvocation {
moduleName: string;

View File

@@ -34,7 +34,7 @@ to check whether the parent PID is still running. So that's what we do here.
const pollIntervalMs = 1000;
export function exitWhenParentExits(parentPid: number, ignoreSigint: boolean) {
export function exitWhenParentExits(parentPid: number) {
setInterval(() => {
if (!processExists(parentPid)) {
// Can't log anything at this point, because out stdout was connected to the parent,
@@ -42,25 +42,6 @@ export function exitWhenParentExits(parentPid: number, ignoreSigint: boolean) {
process.exit();
}
}, pollIntervalMs);
if (ignoreSigint) {
// Pressing ctrl+c in the terminal sends a SIGINT to all processes in the foreground process tree.
// By default, the Node process would then exit before the .NET process, because ASP.NET implements
// a delayed shutdown to allow ongoing requests to complete.
//
// This is problematic, because if Node exits first, the CopyToAsync code in ConditionalProxyMiddleware
// will experience a read fault, and logs a huge load of errors. Fortunately, since the Node process is
// already set up to shut itself down if it detects the .NET process is terminated, all we have to do is
// ignore the SIGINT. The Node process will then terminate automatically after the .NET process does.
//
// A better solution would be to have WebpackDevMiddleware listen for SIGINT and gracefully close any
// ongoing EventSource connections before letting the Node process exit, independently of the .NET
// process exiting. However, doing this well in general is very nontrivial (see all the discussion at
// https://github.com/nodejs/node/issues/2642).
process.on('SIGINT', () => {
console.log('Received SIGINT. Waiting for .NET process to exit...');
});
}
}
function processExists(pid: number) {

Some files were not shown because too many files have changed in this diff Show More