diff --git a/.chronus/changes/mfd-01-2025-0-7-2-3-57.md b/.chronus/changes/mfd-01-2025-0-7-2-3-57.md new file mode 100644 index 0000000000..565d038554 --- /dev/null +++ b/.chronus/changes/mfd-01-2025-0-7-2-3-57.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - "@typespec/http-server-csharp" +--- + +[http-server-csharp]: Fix routing issues with MFD requests diff --git a/packages/http-server-csharp/src/service.ts b/packages/http-server-csharp/src/service.ts index 5d411ae728..7b7dc1436e 100644 --- a/packages/http-server-csharp/src/service.ts +++ b/packages/http-server-csharp/src/service.ts @@ -661,7 +661,7 @@ export async function $onEmit(context: EmitContext) const multipart: boolean = this.#isMultipartRequest(httpOperation); const declParams = !multipart ? this.#emitHttpOperationParameters(httpOperation) - : this.#emitHttpOperationParameters(httpOperation, "HttpRequest request, Stream body"); + : this.#emitHttpOperationParameters(httpOperation, true); if (multipart) { const context = this.emitter.getContext(); @@ -720,14 +720,14 @@ export async function $onEmit(context: EmitContext) ${this.emitter.emitOperationReturnType(operation)} public virtual async Task ${operationName}(${declParams}) { - var boundary = request.GetMultipartBoundary(); + var boundary = Request.GetMultipartBoundary(); if (boundary == null) { return BadRequest("Request missing multipart boundary"); } - var reader = new MultipartReader(boundary, body); + var reader = new MultipartReader(boundary, Request.Body); ${ hasResponseValue ? `var result = await ${this.emitter.getContext().resourceName}Impl.${operationName}Async(${this.#emitOperationCallParameters(httpOperation, "reader")}); @@ -912,7 +912,7 @@ export async function $onEmit(context: EmitContext) #emitHttpOperationParameters( operation: HttpOperation, - bodyParameter?: string, + bodyParameter?: boolean, ): EmitterOutput { const signature = new StringBuilder(); const bodyParam = operation.parameters.body; @@ -930,10 +930,16 @@ export async function $onEmit(context: EmitContext) for (const parameter of requiredParams) { signature.push( code`${this.#emitOperationSignatureParameter(operation, parameter)}${ - ++i < requiredParams.length || bodyParam !== undefined ? ", " : "" + ++i < requiredParams.length ? ", " : "" }`, ); } + if ( + requiredParams.length > 0 && + (optionalParams.length > 0 || (bodyParameter === undefined && bodyParam !== undefined)) + ) { + signature.push(code`, `); + } if (bodyParameter === undefined) { if (bodyParam !== undefined) { signature.push( @@ -942,11 +948,9 @@ export async function $onEmit(context: EmitContext) bodyParam.type, Visibility.Create || Visibility.Update, ), - )} body${optionalParams.length > 0 ? ", " : ""}`, + )} body${requiredParams.length > 0 && optionalParams.length > 0 ? ", " : ""}`, ); } - } else { - signature.push(code`${bodyParameter}${optionalParams.length > 0 ? ", " : ""}`); } i = 0; for (const parameter of optionalParams) { diff --git a/packages/http-server-csharp/test/generation.test.ts b/packages/http-server-csharp/test/generation.test.ts index d9a80d6b23..bc193590cb 100644 --- a/packages/http-server-csharp/test/generation.test.ts +++ b/packages/http-server-csharp/test/generation.test.ts @@ -1123,17 +1123,19 @@ it("handles multipartBody requests and shared routes", async () => { } @sharedRoute - @route("/foo") + @route("/foo/{id}") @post op fooBinary( + @path id: string, @header("content-type") contentType: "multipart/form-data", @multipartBody body: FooRequest ): void; @sharedRoute - @route("/foo") + @route("/foo/{id}") @post op fooJson( + @path id: string, @header("content-type") contentType: "application/json", @body body: FooJsonRequest ): void; @@ -1154,18 +1156,18 @@ it("handles multipartBody requests and shared routes", async () => { "using Microsoft.AspNetCore.WebUtilities;", "using Microsoft.AspNetCore.Http.Extensions;", `[Consumes("multipart/form-data")]`, - "public virtual async Task FooBinary(HttpRequest request, Stream body)", - ".FooBinaryAsync(reader)", - "public virtual async Task FooJson(FooJsonRequest body)", - ".FooJsonAsync(body)", + "public virtual async Task FooBinary(string id)", + ".FooBinaryAsync(id, reader)", + "public virtual async Task FooJson(string id, FooJsonRequest body)", + ".FooJsonAsync(id, body)", ], ], [ "IContosoOperations.cs", [ "using Microsoft.AspNetCore.WebUtilities;", - "Task FooBinaryAsync( MultipartReader reader);", - "Task FooJsonAsync( FooJsonRequest body);", + "Task FooBinaryAsync( string id, MultipartReader reader);", + "Task FooJsonAsync( string id, FooJsonRequest body);", ], ], [