0

I had written an .net MAUI application for my own to work with an third Party API based Application.

Inside the application there is a file picker to get the file.

private async void file_Clicked(object sender, EventArgs e)
{
    var result = await FilePicker.PickAsync(new PickOptions
    {
        PickerTitle = "Datei hochladen ..."
    });

    if (result == null)
        return;

    var stream = await result.OpenReadAsync();

    searchAndReplaceViewModel.ReplaceFile = stream;
    searchAndReplaceViewModel.ReplaceFileName = result.FileName;
    file.Text = result.FileName;
    file.BackgroundColor = Colors.LightGreen;
    
}

in my viewmodel I save the Stream to an object and later on there is the function call to my RestClient:

public object ReplaceFile { get; internal set; }

// A lot of code between

[RelayCommand]
        async Task UploadFile(dtoObjectsBase doc)
        {
            if (IsLoading) return;
            try
            {
                if(App.SearchAndReplaceService.UploadFile(doc, (BufferedStream)ReplaceFile, ReplaceFileName))
                {
                    await Shell.Current.DisplayAlert("Erfolgreich", "Upload Erfolgreich", "Ok");
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Unable to Upload File: {ex.Message}");
                await Shell.Current.DisplayAlert("Error", "Fehler beim Hochladen der Datei", "Ok");
            }
            finally
            {
                IsLoading = false;
            }

        }

Here is the function called above (There is a function from my service class between, but that shouldn't matter. This is the reason for different parameters and Method names.):

public Operation<FileUploadResponse> FileUpload(BufferedStream file, Guid guid, string filename)
        {
            Operation<FileUploadResponse> fileUpload = new();

            FileUpload fileUploadRequest = new()
            {
                Guid = guid,
                RequestStream = file.UnderlyingStream
            };

            try
            {
                var options = new RestClientOptions(Settings.Server)
                {
                    MaxTimeout = -1,
                };
                var client = new RestClient(options);
                var request = new RestRequest(ApiPaths.FileUpload + "?guid=" + guid.ToString(), Method.Post);
                
                request.AddHeader("Content-Type", "multipart/form-data");
                //request.AddFile("MyfactoryImport", );
                byte[] data = new byte[file.Length];
                file.Read(data, 0, (int)file.Length);
                request.AlwaysMultipartFormData = true;
                //request.AddFile("RequestStream", data, RestSharp.ContentType.Binary);
                request.AddFile(filename, data, RestSharp.ContentType.Binary);


                fileUpload.Value = JsonConvert.DeserializeObject<FileUploadResponse>(client.Execute(request).Content);
                fileUpload.Success = true;
                
                //fileUpload.Value = APICall<FileUpload, FileUploadResponse>(fileUploadRequest, ApiPaths.FileUpload);
            }
            catch (Exception ex)
            {
                fileUpload.ErrorMsg = "Fehler bei der API Abfrage: " + ex.Message;
            }

            return fileUpload;
        }

The Restsharp.Response Status Code is "InternalServerError". The Application Log of the API Endpoint logs the following:

HandleFileUpload (general) failed for guid 8f5ae2b3-39e0-41b8-bc18-b60c2b75fc26 | (null) | (ID:(null) System:(null)) System.ApplicationException: Cannot perform file upload. Start boundary not found.

With Postman the upload is no problem, so I don't know what I am making wrong. I think I am handling the stream on the wrong way, but I don't know how to handle it better.

If I try with Postman, the upload works. Postman generated the following Code for Restsharp:

var options = new RestClientOptions("")
{
  MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("https://servername/instance/services/fileupload?guid=6e813e27-bee8-4359-a046-04437365c903", Method.Post);
request.AlwaysMultipartFormData = true;
request.AddFile("file", "dOLC4eFA4/temp.pdf");
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);

The API documentation of the application where I try to Upload only says the following:

POST /server/services/fileupload HTTP/1.1 
Host: localhost 
Accept: application/json
Content-Type: application/json
Content-Length: length

{"Guid":"00000000000000000000000000000000"}

I solved it by using an older RestSharp Version (106.15.0 instead of 110.2.0) I would prefer to use a newer version but for the moment this solution is fine for me.

Andre
  • 1
  • 2
  • I had an issue a while back when trying to upload to a rest API .. My issue is that I was setting the `Content-Type` in the header for the post (I was using `fetch` to the API). Try commenting out that line `request.AddHeader("Content-Type", "multipart/form-data")` From the code you posted I cannot be sure what method is being used to send the data. But if it is indeed a `fetch` you cannot set `Content-Type` – Zak Aug 09 '23 at 19:33
  • what does the API signature of the upload method look like? – Jason Aug 09 '23 at 19:45
  • @Jason : I am not sure what you mean with API signature. The Status Code ist internalServerError. The API documentation only shows the following `POST /server/services/fileupload HTTP/1.1 Host: localhost Accept: application/json Content-Type: application/json Content-Length: length {"Guid":"00000000000000000000000000000000"}` – Andre Aug 09 '23 at 21:39
  • @Zak : Thanks but that didn't work. – Andre Aug 09 '23 at 21:43
  • What does the endpoint you are uploading to look like? What parameters does it require? What do the docs say? See https://stackoverflow.com/questions/8516498/definition-of-a-method-signature – Jason Aug 09 '23 at 22:10
  • @Jason The endpoint is closed source, so I only have the API documentation snippet from the fileupload method posted above. I will add the generated Code from Postman of a working API Call to the endpoint do my original Post. – Andre Aug 09 '23 at 22:25
  • You said "I tried uploading in Postman and it works. What request did you do in Postman? – Alexey Zimarev Aug 10 '23 at 08:41
  • @AlexeyZimarev It's a POST request with Body FormData, where I send the File as "Value": `POST server/services/fileupload?guid=0c5f7810-ccb4-46d3-bc0e-806871084221 HTTP/1.1 Host: servername Cookie: ss-pid=BZfcdCfghysXg2hllpZg Content-Length: 279 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="RequestStream"; filename="/C:/Users/andre/OneDrive/Desktop/test.pdf" Content-Type: (data) ------WebKitFormBoundary7MA4YWxkTrZu0gW--` – Andre Aug 10 '23 at 11:46
  • You can send the request you make with RestSharp to a request bin and you will see the difference. Not sure that kind of guid is there as the parameter. – Alexey Zimarev Aug 10 '23 at 12:57

1 Answers1

0

I solved it by using an older RestSharp Version (106.15.0 instead of 110.2.0) I would prefer to use a newer version but for the moment this solution is fine for me.

Andre
  • 1
  • 2