Skip to content

Commit d55edde

Browse files
authored
Upgrade to .NET 10; misc clean-up (#15)
* Upgrade to .NET 10; convert Startup to Program.cs * Use langversion 14 * Use .NET 10 in actions; use release build * Upgrade Dockerfile to .NET 10 * Update README
1 parent 5bb9919 commit d55edde

8 files changed

Lines changed: 117 additions & 134 deletions

File tree

.github/workflows/dotnet.yml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,25 @@ on:
66
pull_request:
77
branches: [ main ]
88

9+
env:
10+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
11+
DOTNET_CLI_TELEMETRY_OPTOUT: true
12+
BUILD_CONFIGURATION: Release
13+
914
jobs:
1015
build:
1116

1217
runs-on: ubuntu-latest
1318

1419
steps:
15-
- uses: actions/checkout@v2
20+
- uses: actions/checkout@v4
1621
- name: Setup .NET
17-
uses: actions/setup-dotnet@v1
22+
uses: actions/setup-dotnet@v4
1823
with:
19-
dotnet-version: 8.0.x
24+
dotnet-version: 10.0.x
2025
- name: Restore dependencies
2126
run: dotnet restore
2227
- name: Build
23-
run: dotnet build --no-restore
24-
# - name: Test
25-
# run: dotnet test --no-build --verbosity normal
28+
run: dotnet build --no-restore --configuration ${{ env.BUILD_CONFIGURATION }}
29+
- name: Test
30+
run: dotnet test --no-build --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }}

AzureSearchEmulator/AzureSearchEmulator.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<UserSecretsId>6751dc28-24d4-4572-8f44-e652593dd678</UserSecretsId>
66
<Nullable>enable</Nullable>
77
<ImplicitUsings>enable</ImplicitUsings>
8-
<Version>0.0.1</Version>
8+
<Version>1.0.0-beta</Version>
99
<WarningsAsErrors>Nullable</WarningsAsErrors>
10+
<LangVersion>14</LangVersion>
1011
</PropertyGroup>
1112

1213
<ItemGroup>
@@ -15,7 +16,7 @@
1516
<PackageReference Include="Lucene.Net.Highlighter" Version="4.8.0-beta00017" />
1617
<PackageReference Include="Lucene.Net.Queries" Version="4.8.0-beta00017" />
1718
<PackageReference Include="Lucene.Net.QueryParser" Version="4.8.0-beta00017" />
18-
<PackageReference Include="Microsoft.AspNetCore.OData" Version="8.2.3" />
19+
<PackageReference Include="Microsoft.AspNetCore.OData" Version="9.4.1" />
1920
</ItemGroup>
2021

2122
<ItemGroup>

AzureSearchEmulator/Indexing/UpsertIndexDocumentActionBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ protected IEnumerable<IIndexableField> GetDocFields(SearchIndex index)
3333
return from f in index.Fields
3434
join v in Item on f.Name equals v.Key
3535
where v.Value != null
36-
select f.CreateField(v.Value);
36+
select f.CreateField(v.Value!); // [!]: null checked by where clause
3737
}
3838

3939
protected static void MergeDocument(IndexingContext context, Term keyTerm, IEnumerable<IIndexableField> docFields, bool uploadIfMissing)

AzureSearchEmulator/Program.cs

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,96 @@
1-
namespace AzureSearchEmulator;
1+
using System.Text.Json;
2+
using AzureSearchEmulator;
3+
using AzureSearchEmulator.Indexing;
4+
using AzureSearchEmulator.Models;
5+
using AzureSearchEmulator.Repositories;
6+
using AzureSearchEmulator.SearchData;
7+
using AzureSearchEmulator.Searching;
8+
using Microsoft.AspNetCore.Http.Extensions;
9+
using Microsoft.AspNetCore.Mvc;
10+
using Microsoft.AspNetCore.OData;
11+
using Microsoft.Extensions.Options;
12+
using Microsoft.OData.Edm;
13+
using Microsoft.OData.ModelBuilder;
214

3-
public class Program
15+
var builder = WebApplication.CreateBuilder(args);
16+
17+
var model = GetEdmModel();
18+
19+
builder.Services.Configure<EmulatorOptions>(builder.Configuration.GetSection("Emulator"));
20+
21+
const string CorsDefaultPolicyName = "AllowAllOrigins";
22+
23+
builder.Services.AddCors(options =>
24+
{
25+
options.AddPolicy(CorsDefaultPolicyName,
26+
cors =>
27+
{
28+
cors.AllowAnyOrigin()
29+
.AllowAnyMethod()
30+
.AllowAnyHeader();
31+
});
32+
});
33+
34+
builder.Services.AddControllers()
35+
.AddJsonOptions(options =>
36+
{
37+
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
38+
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
39+
})
40+
.AddOData(options =>
41+
options.Count().Filter().Expand().Select().OrderBy().SetMaxTop(1000)
42+
.AddRouteComponents("", model));
43+
44+
builder.Services.AddTransient(sp =>
445
{
5-
public static void Main(string[] args)
46+
var jsonOptions = sp.GetService<IOptions<JsonOptions>>();
47+
48+
if (jsonOptions == null)
649
{
7-
CreateHostBuilder(args).Build().Run();
50+
throw new InvalidOperationException("JsonOptions not registered properly");
851
}
952

10-
public static IHostBuilder CreateHostBuilder(string[] args) =>
11-
Host.CreateDefaultBuilder(args)
12-
.ConfigureWebHostDefaults(webBuilder =>
13-
{
14-
webBuilder.UseStartup<Startup>();
15-
});
16-
}
53+
return jsonOptions.Value.JsonSerializerOptions;
54+
});
55+
56+
builder.Services.AddTransient<ISearchIndexRepository, FileSearchIndexRepository>();
57+
builder.Services.AddSingleton<ILuceneDirectoryFactory, SimpleFSDirectoryFactory>();
58+
builder.Services.AddSingleton<ILuceneIndexReaderFactory, LuceneDirectoryReaderFactory>();
59+
builder.Services.AddTransient<IIndexSearcher, LuceneNetIndexSearcher>();
60+
builder.Services.AddSingleton<ISearchIndexer, LuceneNetSearchIndexer>();
61+
62+
var app = builder.Build();
63+
64+
if (builder.Environment.IsDevelopment())
65+
{
66+
app.UseDeveloperExceptionPage();
67+
}
68+
69+
app.UseCors(CorsDefaultPolicyName);
70+
app.UseODataRouteDebug();
71+
app.UseODataQueryRequest();
72+
app.UseODataBatching();
73+
74+
app.UseRouting();
75+
76+
app.Use((context, next) =>
77+
{
78+
Console.WriteLine($"{context.Request.Method} {context.Request.GetDisplayUrl()}");
79+
return next();
80+
});
81+
82+
app.MapControllers();
83+
84+
await app.RunAsync();
85+
return;
86+
87+
static IEdmModel GetEdmModel()
88+
{
89+
var builder = new ODataConventionModelBuilder();
90+
builder.EnableLowerCamelCase();
91+
92+
var index = builder.EntitySet<SearchIndex>("indexes").EntityType;
93+
index.HasKey(i => i.Name);
94+
95+
return builder.GetEdmModel();
96+
}

AzureSearchEmulator/Searching/ODataQueryVisitor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,9 @@ public Query Visit(GroupByToken tokenIn)
251251
{
252252
throw new NotImplementedException();
253253
}
254+
255+
public Query Visit(RootPathToken tokenIn)
256+
{
257+
throw new NotImplementedException();
258+
}
254259
}

AzureSearchEmulator/Startup.cs

Lines changed: 0 additions & 108 deletions
This file was deleted.

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
1+
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
22
WORKDIR /app
33
EXPOSE 80
44
EXPOSE 443
55

6-
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
6+
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
77
WORKDIR /src
88
COPY ["AzureSearchEmulator/AzureSearchEmulator.csproj", "AzureSearchEmulator/"]
99
RUN dotnet restore "AzureSearchEmulator/AzureSearchEmulator.csproj"
@@ -18,4 +18,4 @@ FROM base AS final
1818
WORKDIR /app
1919
COPY --from=publish /app/publish .
2020
VOLUME [ "/app/indexes" ]
21-
ENTRYPOINT ["dotnet", "AzureSearchEmulator.dll"]
21+
ENTRYPOINT ["dotnet", "AzureSearchEmulator.dll"]

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ We're hiring remote engineers to contribute to cutting-edge AI and custom softwa
1414
## Quick Start
1515

1616
1. Clone the repo.
17-
2. Open AzureSearchEmulator.sln in Visual Studio 2022 and run it,
17+
2. Open AzureSearchEmulator.sln in Visual Studio 2026, Rider, or Visual Studio Code with C# Dev Kit and run it,
1818
or cd to the `AzureSearchEmulator` folder and run `dotnet run` from the command-line.
1919

2020
## Features
@@ -26,7 +26,7 @@ This application is *not* intended for use in production or to replace Azure Sea
2626
There is another [azure-search-emulator](https://github.com/tomasloksa/azure-search-emulator) project that may or may not be a better
2727
fit for your needs, depending on what you're trying to do. Compared to that project, this project:
2828

29-
* Has no external service/runtime dependencies beyond .NET 6
29+
* Has no external service/runtime dependencies beyond .NET 10
3030
* Can be run and debugged simply with F5 in Visual Studio, or `dotnet run` on the command line
3131
* Does not require Docker or any kind of containers/virtualization, but can be run with Docker if you prefer (see below)
3232
* Does not require Solr (or Java), Docker Compose, or any kind of orchestration

0 commit comments

Comments
 (0)