I am trying to upload FormData in my Blazor WASM client, but I get a HTTP 405 “Method not allowed” error. Any idea what I am doing wrong?
I am running ServiceStack 8.6.1 with .NET8 on Windows
The stacktrace is
at ServiceStack.JsonApiClient.ThrowWebServiceException[ErrorResponse](HttpResponseMessage httpRes, Object request, String requestUri, Object response) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Client/JsonApiClient.cs:line 941
at ServiceStack.JsonApiClient.ThrowResponseTypeException[String](HttpResponseMessage httpRes, Object request, String requestUri, Object response) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Client/JsonApiClient.cs:line 866
at ServiceStack.JsonApiClient.ThrowIfError[String](Func`1 fn, HttpResponseMessage httpRes, Object request, String requestUri) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Client/JsonApiClient.cs:line 828
at ServiceStack.JsonApiClient.ConvertToResponse[MultiCrudResponse`1](HttpResponseMessage httpRes, String httpMethod, String absoluteUrl, Object request) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Client/JsonApiClient.cs:line 775
at ServiceStack.JsonApiClient.<SendFormAsync>d__282`1[[Framework.ServiceModel.TypesNs.CoreNs.MultiCrudResponse`1[[Framework.ServiceModel.TypesNs.AttachmentNs.FileStore, Framework.ServiceModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Framework.ServiceModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Client/JsonApiClient.cs:line 1626
at ServiceStack.ServiceGatewayAsyncWrappers.<ApiFormAsync>d__17`1[[Framework.ServiceModel.TypesNs.CoreNs.MultiCrudResponse`1[[Framework.ServiceModel.TypesNs.AttachmentNs.FileStore, Framework.ServiceModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Framework.ServiceModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Client/ServiceGatewayExtensions.cs:line 300
Blazor WASM Client code
//TableFileStoreSummary.razor.cs
namespace Framework.Client.Components.Table;
public partial class TableFileStoreSummary : Page.TableComponent<FileStoreSummary>
{
// FileSelectFileInfo is a Telerik class that provides file data from an upload dialog
private async Task<string?> UploadFile(FileSelectFileInfo fileInfo)
{
var request = new CreateAttachedFile
{
AttachedId = AttachedId,
AttachedSource = AttachedSource,
AppFile = new FileStore
{
FileName = fileInfo.Name,
FileSize = fileInfo.Size,
Closed = false,
AttachedSource = AttachedSource,
AttachedId = AttachedId
}
};
string mimeType = FileExtensionMimeMapping
.FirstOrDefault(item => item.Item1.ToLower().Contains(fileInfo.Extension.ToLower()))
.Item2 ?? string.Empty;
try
{
byte[] byteArray = new byte[fileInfo.Size];
await using MemoryStream ms = new(byteArray);
await fileInfo.Stream.CopyToAsync(ms);
ms.Position = 0;
using var content = new MultipartFormDataContent()
.AddParams(request)
.AddFile(nameof(CreateAttachedFile.AppFile), fileInfo.Name, ms, mimeType);
Console.WriteLine("Uploading file length: " + ms.Length);
var uploadUrl = request.ToPostUrl();
// **** HTTP 405 on next line ***
var api = await ApiFormAsync<FileStore>(uploadUrl, content);
if (!api.Succeeded)
{
api.Response.PrintDump();
}
return "uploaded";
}
catch (Exception ex)
{
Console.WriteLine(ex);
return ex.Message;
}
}
}
ServiceInterface
Works correctly using API Explorer to upload a file, but never gets called my client because of 405 error.
namespace Framework.ServiceInterface.AttachmentNs;
public class FileStoreService(IAutoQueryDb autoQuery) : Service
{
// Does not get called, because of HTTP 405 error
public FileStore Post(CreateAttachedFile request)
{
_ = request ?? throw new ArgumentNullException(nameof(request));
// code omitted, but work correctly using API Explorer to upload file
}
}
ServiceModel
namespace Framework.ServiceModel.AttachmentNs;
[Route("/api/attachment/filestore/file", "POST")]
[AutoApply(Behavior.AuditCreate)]
public class CreateAttachedFile : IReturn<MultiCrudResponse<FileStore>>, IPost
{
public Guid AttachedId { get; init; }
public string AttachedSource { get; init; } = null!;
[Input(Type = "file")]
public FileStore AppFile { get; init; } = null!;
}
ServiceModel Type:
namespace Framework.ServiceModel.TypesNs.AttachmentNs;
// DB table to hold file metadata
[Schema("Attachment")]
[DataContract]
public record FileStore
{
[AutoId]
[DataMember, Required]
public Guid Id { get; init; }
[DataMember, Required]
public Guid AttachedId { get; init; }
[DataMember, Required]
public string AttachedSource { get; init; } = null!;
[DataMember, Required]
public string FileName { get; init; } = null!;
[DataMember, Required]
public long FileSize { get; init; }
[DataMember, Required]
public DateTime AttachedTstp { get; init; }
[DataMember, Required]
public Guid AttachedBy { get; init; }
[IgnoreOnInsert, IgnoreOnUpdate]
[DataMember, Required]
public bool Closed { get; init; }
}