├── .gitattributes
├── .gitignore
├── KestrelHostedWithinIIS
├── KestrelHostedWithinIIS.csproj
├── Program.cs
├── Startup.cs
├── appsettings.Development.json
└── appsettings.json
├── README.md
├── WpfAppWithGrpcServer
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
└── WpfAppWithGrpcServer.csproj
├── gRPCLibrary
├── GrpcServer.cs
├── GrpcServerExtensions.cs
├── GrpcServerOptions.cs
├── Protos
│ └── greet.proto
├── Services
│ └── GreeterService.cs
└── gRPCLibrary.csproj
└── gRPCSamples.sln
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.doc diff=astextplain
2 | *.DOC diff=astextplain
3 | *.docx diff=astextplain
4 | *.DOCX diff=astextplain
5 | *.dot diff=astextplain
6 | *.DOT diff=astextplain
7 | *.pdf diff=astextplain
8 | *.PDF diff=astextplain
9 | *.rtf diff=astextplain
10 | *.RTF diff=astextplain
11 |
12 | *.jpg binary
13 | *.png binary
14 | *.gif binary
15 |
16 | *.cs text=auto diff=csharp
17 | *.vb text=auto
18 | *.resx text=auto
19 | *.c text=auto
20 | *.cpp text=auto
21 | *.cxx text=auto
22 | *.h text=auto
23 | *.hxx text=auto
24 | *.py text=auto
25 | *.rb text=auto
26 | *.java text=auto
27 | *.html text=auto
28 | *.htm text=auto
29 | *.css text=auto
30 | *.scss text=auto
31 | *.sass text=auto
32 | *.less text=auto
33 | *.js text=auto
34 | *.lisp text=auto
35 | *.clj text=auto
36 | *.sql text=auto
37 | *.php text=auto
38 | *.lua text=auto
39 | *.m text=auto
40 | *.asm text=auto
41 | *.erl text=auto
42 | *.fs text=auto
43 | *.fsx text=auto
44 | *.hs text=auto
45 |
46 | *.csproj text=auto
47 | *.vbproj text=auto
48 | *.fsproj text=auto
49 | *.dbproj text=auto
50 | *.sln text=auto eol=crlf
51 |
52 | *.sh eol=lf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | [Oo]bj/
2 | [Bb]in/
3 | TestResults/
4 | .nuget/
5 | *.sln.ide/
6 | _ReSharper.*/
7 | .idea/
8 | packages/
9 | artifacts/
10 | PublishProfiles/
11 | .vs/
12 | *.user
13 | *.suo
14 | *.cache
15 | *.docstates
16 | _ReSharper.*
17 | nuget.exe
18 | *net45.csproj
19 | *net451.csproj
20 | *k10.csproj
21 | *.psess
22 | *.vsp
23 | *.pidb
24 | *.userprefs
25 | *DS_Store
26 | *.ncrunchsolution
27 | *.*sdf
28 | *.ipch
29 | *.swp
30 | *~
31 | .build/
32 | .testPublish/
33 | launchSettings.json
34 | BenchmarkDotNet.Artifacts/
35 | BDN.Generated/
36 | binaries/
37 | global.json
38 |
--------------------------------------------------------------------------------
/KestrelHostedWithinIIS/KestrelHostedWithinIIS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/KestrelHostedWithinIIS/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace KestrelHostedWithinIIS
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/KestrelHostedWithinIIS/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using gRPCLibrary;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.AspNetCore.Http;
9 | using Microsoft.Extensions.DependencyInjection;
10 | using Microsoft.Extensions.Hosting;
11 |
12 | namespace KestrelHostedWithinIIS
13 | {
14 | public class Startup
15 | {
16 | // This method gets called by the runtime. Use this method to add services to the container.
17 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
18 | public void ConfigureServices(IServiceCollection services)
19 | {
20 | services.AddStandaloneGrpcServer();
21 | }
22 |
23 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
24 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
25 | {
26 | if (env.IsDevelopment())
27 | {
28 | app.UseDeveloperExceptionPage();
29 | }
30 |
31 | app.UseRouting();
32 |
33 | app.UseEndpoints(endpoints =>
34 | {
35 | endpoints.MapGet("/", async context =>
36 | {
37 | await context.Response.WriteAsync("Hello World!");
38 | });
39 | });
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/KestrelHostedWithinIIS/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/KestrelHostedWithinIIS/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gRPC Samples
2 |
3 | Samples showing how to run a gRPC server in a WPF application and as a standalone server running in IIS (Kestrel and IIS running on different ports).
4 | WPF has a known issue generating the appropriate gRPC and proto files (see https://docs.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0#wpf-projects-unable-to-generate-grpc-c-assets-from-proto-files)
5 | so the gRPC service is in a class library. Code generation works fine in web projects but I wanted to share the code.
--------------------------------------------------------------------------------
/WpfAppWithGrpcServer/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/WpfAppWithGrpcServer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace WpfAppWithGrpcServer
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/WpfAppWithGrpcServer/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/WpfAppWithGrpcServer/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | using gRPCLibrary;
16 | using Microsoft.Extensions.DependencyInjection;
17 | using Microsoft.Extensions.Hosting;
18 |
19 | namespace WpfAppWithGrpcServer
20 | {
21 | ///
22 | /// Interaction logic for MainWindow.xaml
23 | ///
24 | public partial class MainWindow : Window
25 | {
26 | // TODO: Stop this some where...
27 | private IHost _host;
28 |
29 | public MainWindow()
30 | {
31 | _host = new HostBuilder()
32 | .ConfigureServices(services =>
33 | {
34 | services.AddStandaloneGrpcServer(o =>
35 | {
36 | // Change the port
37 | o.ListenLocalhost(5007);
38 | });
39 | })
40 | .Build();
41 |
42 | _host.Start();
43 |
44 | InitializeComponent();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/WpfAppWithGrpcServer/WpfAppWithGrpcServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | netcoreapp3.0
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/gRPCLibrary/GrpcServer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.AspNetCore.Server.Kestrel.Core;
9 | using Microsoft.Extensions.DependencyInjection;
10 | using Microsoft.Extensions.Hosting;
11 | using Microsoft.Extensions.Logging;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace gRPCLibrary
15 | {
16 | // This configures a GrpcServer inside of an existing application
17 | public class GrpcServer : IHostedService
18 | {
19 | private IHost _host;
20 | private readonly ILoggerFactory _loggerFactory;
21 | private readonly GrpcServerOptions _options;
22 |
23 | public GrpcServer(ILoggerFactory loggerFactory, IOptions options)
24 | {
25 | _loggerFactory = loggerFactory;
26 | _options = options.Value;
27 | }
28 |
29 | public Task StartAsync(CancellationToken cancellationToken)
30 | {
31 | _host = new HostBuilder()
32 | .ConfigureServices(services =>
33 | {
34 | // Add the logger factory so that logs are configured by the main host
35 | services.AddSingleton(_loggerFactory);
36 | })
37 | .ConfigureWebHost(webHostBuilder =>
38 | {
39 | webHostBuilder.UseKestrel(options =>
40 | {
41 | options.ConfigureEndpointDefaults(defaults =>
42 | {
43 | // gRPC requires HTTP/2
44 | defaults.Protocols = HttpProtocols.Http2;
45 | });
46 |
47 | _options.ConfigureServerOptions(options);
48 | });
49 |
50 | webHostBuilder.ConfigureServices(services =>
51 | {
52 | services.AddGrpc(options =>
53 | {
54 | _options.ConfigureGrpcOptions(options);
55 | });
56 | });
57 |
58 | webHostBuilder.Configure(app =>
59 | {
60 | app.UseRouting();
61 | app.UseEndpoints(endpoints =>
62 | {
63 | endpoints.MapGrpcService();
64 | });
65 | });
66 | })
67 | .Build();
68 |
69 | return _host.StartAsync(cancellationToken);
70 | }
71 |
72 | public Task StopAsync(CancellationToken cancellationToken)
73 | {
74 | return _host?.StopAsync(cancellationToken) ?? Task.CompletedTask;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/gRPCLibrary/GrpcServerExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Grpc.AspNetCore.Server;
5 | using gRPCLibrary;
6 | using Microsoft.AspNetCore.Server.Kestrel.Core;
7 |
8 | namespace Microsoft.Extensions.DependencyInjection
9 | {
10 | public static class GrpcServerExtensions
11 | {
12 | public static IServiceCollection AddStandaloneGrpcServer(this IServiceCollection services,
13 | Action configureServer = null,
14 | Action configureGrpc = null)
15 | {
16 | // Add the standalone GrpcServer (it'll only be added once)
17 | services.AddHostedService();
18 |
19 | services.Configure(options =>
20 | {
21 | if (configureServer != null)
22 | {
23 | options.ConfigureServerOptions += configureServer;
24 | }
25 |
26 | if (configureGrpc != null)
27 | {
28 | options.ConfigureGrpcOptions += configureGrpc;
29 | }
30 | });
31 | return services;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/gRPCLibrary/GrpcServerOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Grpc.AspNetCore.Server;
5 | using Microsoft.AspNetCore.Server.Kestrel.Core;
6 |
7 | namespace gRPCLibrary
8 | {
9 | public class GrpcServerOptions
10 | {
11 | public Action ConfigureGrpcOptions { get; set; } = o => { };
12 | public Action ConfigureServerOptions { get; set; } = o => { };
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/gRPCLibrary/Protos/greet.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | option csharp_namespace = "GrpcServices";
4 |
5 | package Greet;
6 |
7 | // The greeting service definition.
8 | service Greeter {
9 | // Sends a greeting
10 | rpc SayHello (HelloRequest) returns (HelloReply);
11 | }
12 |
13 | // The request message containing the user's name.
14 | message HelloRequest {
15 | string name = 1;
16 | }
17 |
18 | // The response message containing the greetings.
19 | message HelloReply {
20 | string message = 1;
21 | }
22 |
--------------------------------------------------------------------------------
/gRPCLibrary/Services/GreeterService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Grpc.Core;
6 | using GrpcServices;
7 | using Microsoft.Extensions.Logging;
8 |
9 | namespace gRPCLibrary
10 | {
11 | public class GreeterService : Greeter.GreeterBase
12 | {
13 | private readonly ILogger _logger;
14 |
15 | public GreeterService(ILogger logger)
16 | {
17 | _logger = logger;
18 | }
19 |
20 | public override Task SayHello(HelloRequest request, ServerCallContext context)
21 | {
22 | return Task.FromResult(new HelloReply
23 | {
24 | Message = "Hello " + request.Name
25 | });
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/gRPCLibrary/gRPCLibrary.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/gRPCSamples.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29418.71
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KestrelHostedWithinIIS", "KestrelHostedWithinIIS\KestrelHostedWithinIIS.csproj", "{74E7FDCD-615A-47ED-A0AC-DE87D07C2B0B}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfAppWithGrpcServer", "WpfAppWithGrpcServer\WpfAppWithGrpcServer.csproj", "{1CB07795-0327-4308-9ED3-3D56FC5E550A}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gRPCLibrary", "gRPCLibrary\gRPCLibrary.csproj", "{03A7A3B2-1CFF-4406-9431-A69894A1CD4C}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {74E7FDCD-615A-47ED-A0AC-DE87D07C2B0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {74E7FDCD-615A-47ED-A0AC-DE87D07C2B0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {74E7FDCD-615A-47ED-A0AC-DE87D07C2B0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {74E7FDCD-615A-47ED-A0AC-DE87D07C2B0B}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {1CB07795-0327-4308-9ED3-3D56FC5E550A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {1CB07795-0327-4308-9ED3-3D56FC5E550A}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {1CB07795-0327-4308-9ED3-3D56FC5E550A}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {1CB07795-0327-4308-9ED3-3D56FC5E550A}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {03A7A3B2-1CFF-4406-9431-A69894A1CD4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {03A7A3B2-1CFF-4406-9431-A69894A1CD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {03A7A3B2-1CFF-4406-9431-A69894A1CD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {03A7A3B2-1CFF-4406-9431-A69894A1CD4C}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {403B1E1E-E8DF-4520-8333-CD93A1024561}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------