I've got a core project with a bunch of proto files in it. The core project does not have any GRPC code gen packages installed.
I'm trying to reference these proto files in a service that will compile and consume them.
So I used dotnet-grpc
to add these files to this project which resulted in the following itemgroup
being added to the csproj
<ItemGroup>
<Protobuf Include="..\BonnieAndClydesdale.Core\Protos\Enums\HorseGender.proto" Link="Protos\Enums\HorseGender.proto"/>
<Protobuf Include="..\BonnieAndClydesdale.Core\Protos\Models\AdDetails.proto" Link="Protos\Models\AdDetails.proto"/>
<Protobuf Include="..\BonnieAndClydesdale.Core\Protos\Models\HorseDetails.proto" Link="Protos\Models\HorseDetails.proto"/>
<Protobuf Include="..\BonnieAndClydesdale.Core\Protos\Services\AdService.proto" Link="Protos\Services\AdService.proto"/>
</ItemGroup>
However, now I'm getting errors that my proto files can't find their various imports.
For example:
syntax = "proto3";
import "HorseDetails.proto";
option csharp_namespace = "BonnieAndClydesdale.Core.Models";
package Ads;
message AdDetails {
string title = 1;
double asking_price = 2; //TODO - Custom Decimal
string short_description = 3;
string image_url = 4;
string location = 5;
HorseDetails horse_details = 6;
}
Can't locate HorseDetails.proto
.
I'm kind of confused as to what's going on here since I've not changed any of the file layouts and this works fine if the files are just placed directly in my service project.
Any ideas?
More Details:
Here are the proto files:
HorseGender.proto
syntax = "proto3";
option csharp_namespace = "BonnieAndClydesdale.Core.Enums";
package Ads;
enum HorseGender{
Stallion = 0;
Gelding = 1;
Mare = 2;
}
AdDetails.proto
syntax = "proto3";
import "HorseDetails.proto";
option csharp_namespace = "BonnieAndClydesdale.Core.Models";
package Ads;
message AdDetails {
string title = 1;
double asking_price = 2; //TODO - Custom Decimal
string short_description = 3;
string image_url = 4;
string location = 5;
HorseDetails horse_details = 6;
}
HorseDetails.proto
syntax = "proto3";
import "HorseGender.proto";
option csharp_namespace = "BonnieAndClydesdale.Core.Models";
package Ads;
message HorseDetails
{
string name = 1;
int32 age_in_years = 2;
HorseGender gender = 3;
string breed = 4;
float height = 5; // TODO - custom decimal
}
AdService.proto
syntax = "proto3";
import "AdDetails.proto";
option csharp_namespace = "BonnieAndClydesdale.Core";
package Ads;
service AdService {
rpc GetAds (AdRequest) returns (AdReply);
}
message AdRequest {
}
message AdReply {
repeated AdDetails AdDetails = 1;
}
And the file-tree:
.
├── BonnieAndClydesdale.AdService
│ ├── BonnieAndClydesdale.AdService.csproj
│ ├── Dockerfile
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Repositories
│ │ ├── AdsRepositoryStub.cs
│ │ └── IAdsRepository.cs
│ └── Services
│ └── AdService.cs
├── BonnieAndClydesdale.Core
│ ├── BonnieAndClydesdale.Core.csproj
│ ├── Clients
│ │ ├── AdServiceClientStub.cs
│ │ └── IAdServiceClient.cs
│ ├── Enums
│ │ └── HorseGender.cs
│ ├── Models
│ │ ├── AdDetails.cs
│ │ └── HorseDetails.cs
│ └── Protos
│ ├── Enums
│ │ └── HorseGender.proto
│ ├── Models
│ │ ├── AdDetails.proto
│ │ └── HorseDetails.proto
│ └── Services
│ └── AdService.proto
├── BonnieAndClydesdale.MainSite
│ ├── _Imports.razor
│ ├── App.razor
│ ├── BonnieAndClydesdale.MainSite.csproj
│ ├── Pages
│ │ ├── ForSale.cs
│ │ ├── ForSale.razor
│ │ └── Index.razor
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Shared
│ │ ├── Components
│ │ │ ├── AdCard.cs
│ │ │ └── AdCard.razor
│ │ └── Layouts
│ │ ├── MainLayout.cs
│ │ ├── MainLayout.razor
│ │ └── NavMenu.razor
│ └── wwwroot
│ ├── favicon.ico
│ ├── index.html
│ └── sample-data
│ └── weather.json
└── BonnieAndClydesdale.sln
CodePudding user response:
As your .proto files are in different directories, you will need to specify the import directories. You can do that with AdditionalImportDirs
in the <Protobuf ... />
.
So the ItemGroup became something like this:
<ItemGroup>
<Protobuf
Include="..\BonnieAndClydesdale.Core\Protos\Enums\HorseGender.proto"
Link="Protos\Enums\HorseGender.proto" />
<Protobuf
AdditionalImportDirs="..\BonnieAndClydesdale.Core\Protos"
Include="..\BonnieAndClydesdale.Core\Protos\Models\AdDetails.proto"
Link="Protos\Models\AdDetails.proto" />
<Protobuf
AdditionalImportDirs="..\BonnieAndClydesdale.Core\Protos"
Include="..\BonnieAndClydesdale.Core\Protos\Models\HorseDetails.proto"
Link="Protos\Models\HorseDetails.proto" />
<Protobuf
AdditionalImportDirs="..\BonnieAndClydesdale.Core\Protos"
Include="..\BonnieAndClydesdale.Core\Protos\Services\AdService.proto"
Link="Protos\Models\HorseDetails.proto" />
</ItemGroup>
As you can I decided to specify the import dir to be the root of all the protos. So now, you will need to import like this:
AdDetails.proto
...
import "Models/HorseDetails.proto";
...
HorseDetails.proto
...
import "Enums/HorseGender.proto";
...
AdService.proto
...
import "Models/AdDetails.proto";
...
This is a design choice I made. You could totally be more specific with the AdditionalImportDirs
and thus only specify the file name for example but adding the root directory is a little bit more clear in my opinion.
After that you could obviously make that less verbose by adding a path variable to ..\BonnieAndClydesdale.Core\Protos
in your PropertyGroup
. This will also save you from typo errors.
Let me know if it helped and let me know if you need anything.