3

I want to define such a router or Map for my gRPC Server using Enum or similar method

I've a simple Service which named ServerHubService and a Hubs folder which have some classes in it which will be handle every request will be passed by client to my gRPC server

Here is ScreenShot of my Project Project Structure Now as can be seen in the photo The contents of the file are also the image below HubMap.cs

as you can see i want to define a switch case statment to run diffrent classes

Here is my ServiceHubService gRPC class ServerHubService.cs

and finally this my client side call grpc-client.cs

visual studio 2019 ver 16.10

Here is my ServerHub.proto file :

syntax = "proto3";

option csharp_namespace = "NetPlus.Server.Core";

package server;


service ServereHub  {

rpc ActionManager (ActionRequest) returns (ActionResult);

}

message ActionRequest {
    string ActionType = 1;
}

message ActionResult {
    string ActionResultType = 1;
}

my ServerHubService.cs :

using Microsoft.Extensions.Logging;
using NetPlus.Server.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NetPlus.Server.Core.Hubs;
namespace NetPlus.Server.Core
{
    public class ServerHubService : ServereHub.ServereHubBase
    {
        private readonly ILogger<ServerHubService> _logger;

       public ServerHubService(ILogger<ServerHubService> logger)
        {
            _logger = logger;
        }

        public override Task<ActionResult> ActionManager(ActionRequest request, ServerCallContext context)
        {
            HubMap map = new HubMap();
            HubMap.HubSelector selector;

         
            return Task.FromResult(new ActionResult
            {
                ActionResultType = map.HubProccessor(selector)
            }) ;
        }
    }
    
}

and Hubmap.cs

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NetPlus.Server.Core.Hubs
{
    public class HubMap
    {
        Switcher switcher = new Switcher();

        public string HubNameResult { get; set; }
        public   enum HubSelector
        {
            SwitchServer_Off  = 1

        }
       
        public  string HubProccessor(HubSelector hName) =>
          
        
            hName switch
            {
                HubSelector.SwitchServer_Off => switcher.PutOffline(),
               
                _=> "Error Proccesing  Hub"
            };
        
        
    }

}

Problem 2 : Whats this error enter image description here

Question 2:

How to Detect Defined enums in proto file and proccess in HubMap.cs

SecGen Unity
  • 35
  • 1
  • 5
  • The main issue here appears to be simply that you aren't using `async`; that should be `public async Task CustomMethodAsync(...)` or `public async ValueTask CustomMethodAsync(...)`, no? – Marc Gravell Mar 30 '21 at 11:07
  • no i get error ' can not convert from HubMap.HubSelector to string – SecGen Unity Mar 30 '21 at 11:11
  • 1
    you're also showing some broken code in `ActionManager` that is due to "definite assignment" (of `selector`); it would be really good if you could ask a *specific* question, making it clear what problem you're asking about; in particular, saying what compiler error you're asking about (the red squigglies) – Marc Gravell Mar 30 '21 at 11:11
  • 1
    "no i get error ' can not convert from HubMap.HubSelector to string" - and we would have guessed that how, exactly? that's exactly why I'm saying to be explicit; now; we can't see your `ActionRequest` type, so ... help us out here; is `ActionRequest.ActionType` defined as `string`? and: should it be? – Marc Gravell Mar 30 '21 at 11:13
  • Additionally, showing all the code as text within the question, rather than as screenshots, would help... – Jon Skeet Mar 30 '21 at 11:13
  • simply i want to pass enum element as grpc request – SecGen Unity Mar 30 '21 at 11:13
  • @SecGenUnity "simply i want to pass enum element as grpc request" - that works perfectly fine, assuming the field is *defined* as that enum in the .proto; we also can't see your .proto (note: you can't pass *just* an enum, but you can pass a message type that *has* just an enum) – Marc Gravell Mar 30 '21 at 11:14
  • As a side note: I should add that if both your client and server are C#, you can bypass the .proto stage entirely - via protobuf-net.Grpc, which uses a code-first approach: https://protobuf-net.github.io/protobuf-net.Grpc/gettingstarted – Marc Gravell Mar 30 '21 at 11:38

2 Answers2

5

If you want to pass an enum over gRPC: define the enum in gRPC terms:

syntax = "proto3";

option csharp_namespace = "NetPlus.Server.Core";

package server;

enum ActionType
{   // whatever contents...
    Foo = 0;
    Bar = 1;
    Blap = 2;
}
enum ActionResultType
{
    // ... etc
}
service ServereHub  {
   rpc ActionManager (ActionRequest) returns (ActionResult);
}

message ActionRequest {
    ActionType Action = 1;
}

message ActionResult {
    ActionResultType Result = 1;
}

And use the generated enums. If you don't want to do that and want to use string instead: then all the conversions back and fore are up to you; ToString() and Enum.Parse are your friends.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • do i need to use meesage keyword before enum? – SecGen Unity Mar 30 '21 at 11:29
  • @SecGenUnity no; enums *can* be nested inside a `message` if you so choose and if that makes sense, but they do not need to be - they can be top-level like shown. It could also make sense to define `ActionType` inside `ActionRequest` and `ActionResultType` inside `ActionResult` - **if** they aren't used anywhere else – Marc Gravell Mar 30 '21 at 11:35
  • What do you do if the enum has an OriginalName? In my case, the C# enum is Upper Camel Cased and the original name is all capitals for the most part. I realize I could hack it with some janky string manipulation, but would like to understand what the heck gRPC _expects_ me to do? – John Zabroski Oct 27 '22 at 00:13
  • 1
    @JohnZabroski gRPC (by default) uses the binary protobuf encoding, which doesn't care about names - names are not transmitted – Marc Gravell Oct 27 '22 at 06:03
  • Some of the enums are mapped on the message as strings, not enum values - others are straightforward and mapped on the message as an enum as well. This is my first gRPC project, as a client API user. I'm sure I will figure this out in a few days time, but I could not find straightforward explanations on enums and what purpose OriginalName serves. e.g., do I need to call a special reflection helper to put the OriginalName value in the string field in the message? Trying to Google/Bing/Brave this has been kind of painful. – John Zabroski Oct 28 '22 at 17:56
  • 1
    @JohnZabroski vanilla protobuf doesn't have an OriginalName AFAIK; what language/toolset are you using here? And again, usually the binary form: doesn't use names. If you're doing a string convert, that's up to you... – Marc Gravell Oct 29 '22 at 22:48
  • I had a beginner misunderstanding. OriginalName is just for language-specific customizations to follow naming conventions of that ecosystem. – John Zabroski Nov 01 '22 at 13:36
2

I would recommend you to take a look at the google protobuf guidelines.

Naming conventions

Designpatterns

The generated Enums will be PascalCase (FOO_BAR => FooBar)

Leppin
  • 241
  • 1
  • 7
  • So the convention is that 0 in an enum should denote "unspecified"? Is that like a nullable value type in C#? It looks like as of proto version 3.15, the "optional" keyword is available and should be used instead. https://stackoverflow.com/a/62566052/1040437 – John Zabroski Nov 01 '22 at 14:41
  • 1
    @JohnZabroski i think it's more about versioning than making it nullable, if you have a new version of the service (v2) with a new enum variable and want to call it from an old client the value will be unspecified by default – Leppin Nov 02 '22 at 07:45