简体   繁体   中英

Post from xamarin to restful API

I am trying to make an API call from xamarin, this is my first Full mobile app calling restful API (.NetCore3.1) with a Angular WebApp. All other API calls from the xamarin app are working, The issue is I need to send a File with an object, file can be .doc .png etc.

GrantApplication.cs API Endpoint

    public class FileProvider
    {
        public string GA { get; set; }
        public IList<IFormFile> Files { get; set; }
    }


         [HttpPost]
        [Route("[action]")]
        public ActionResult SubmitGrantApplication([FromForm] FileProvider fileProvider)
        {
            try
            {
                var ga = fileProvider;
                byte[] fileContent = null;
                var files = Request.Form.Files.Any() ? Request.Form.Files : new FormFileCollection();
                var grant = JsonConvert.DeserializeObject<GrantApplication>(ga.GA);
               ...
            }
        }

GrantService.cs Call made from the mobile app: This call is returning a 400 response with no clear indication why. I am trying to figure out why, And my postman skills aren't that great to convert the code to postman.

The error returned at #5.
::"Object reference not set to an instance of an object."

public class GrantService
    {
        public static async Task<GrantApplication> SubmitGrant(GrantApplication ga,string file, string FileName, StreamContent FileData)
        {
                Uri requestUri = new Uri($"{ApiSettings.ApiBaseUrl}/grantapplication/SubmitGrantApplication");
                try
                {
                    var upfilebytes = File.ReadAllBytes(file);
                    //using (HttpClient client = new HttpClient())
                    //{
                    //    //MultipartFormDataContent content = new MultipartFormDataContent();
                    //    //ByteArrayContent baContent = new ByteArrayContent(upfilebytes);
                    //    //StringContent GA = new StringContent(JsonConvert.SerializeObject(ga));
                    //    //content.Add(baContent, "Files", FileName);
                    //    //content.Add(GA, "GA");
                    //    //Console.WriteLine(content);
                    //    //var response = await client.PostAsync(requestUri, content);
                    //    //Console.WriteLine(await response.Content.ReadAsStringAsync());
                    //    //return ga;
                    //}
                    using (var formContent = new MultipartFormDataContent())
                    {
                        formContent.Headers.ContentType.MediaType = "multipart/form-data";
                        // 3. Add the filename C:\\... + fileName is the path your file
                        Stream fileStream = File.OpenRead(file);
                        formContent.Add(new StreamContent(fileStream), FileName, FileName);
                        var payload = JsonConvert.SerializeObject(ga);
                        HttpContent content = new StringContent(payload, Encoding.UTF8, "application/json");
                        formContent.Add(content, "GA");
                        using (var client = new HttpClient())
                        {
                            // Bearer Token header if needed
                            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("multipart/form-data"));

                            try
                            {
                                // 4.. Execute the MultipartPostMethod
                                var message = await client.PostAsync(requestUri, formContent);
                                // 5.a Receive the response
                                var result = await message.Content.ReadAsStringAsync();
                                Console.WriteLine(result);
                            }
                            catch (Exception ex)
                            {
                                // Do what you want if it fails.
                                throw ex;
                            }
                        }
                    }
                    return ga;
                }
                catch(Exception ex)
                {
                     Console.WriteLine(ex);
                    return ga;
                }
           
        }
    }

Web System Angular API call

public SubmitGrantApplication(grantApplication){
    grantApplication.memberId = JSON.parse(sessionStorage.getItem("LoggedInUser")).memberID;
    grantApplication.ClientID = JSON.parse(sessionStorage.getItem("LoggedInUser")).clientID;
    this.headers = new HttpHeaders({ 'Content-Type' :  'multipart/form-data' });
    this.headers = new HttpHeaders({ 'Accept':  'multipart/form-data'});
    let myFormData: FormData = new FormData();
    myFormData.append("Files", grantApplication.documentContent);
    myFormData.append("GA", JSON.stringify(grantApplication));
    return this.http.post<GrantApplication>(this.url+"SubmitGrantApplication", myFormData , { headers: this.headers }).pipe(
    ).toPromise();
  }
  

Swagger

Swagger Doc

Works Angular API Call Works Payload Angular

I tried to replicate your case and with same code (unused code was removed)

It works, can you share whole response of PostAsync? url, response code and other properties can tell us something

    public static async Task<dynamic> SubmitGrant(object ga, string file, string FileName)
    {
        var upfilebytes = File.ReadAllBytes(file);
        using (HttpClient client = new HttpClient())
        {
            Uri requestUri = new Uri($"https://localhost:44341/grantapplication/SubmitGrantApplication");
            MultipartFormDataContent content = new MultipartFormDataContent();
            ByteArrayContent baContent = new ByteArrayContent(upfilebytes);
            StringContent GA = new StringContent(JsonConvert.SerializeObject(ga));
            content.Add(baContent, "Files", FileName);
            content.Add(baContent, "Files", 1 + FileName); /* test 2 files */
            content.Add(GA, "GA");
            Console.WriteLine(content);
            var response = await client.PostAsync(requestUri, content);
            Console.WriteLine(response);
            return ga;
        }
    }

Calling Method

await SubmitGrant(new { Test = 123 }, "C:\\Temp\\MyPicture.jpg", "MyPicture.jpg");

Receiving Data and Files

在此处输入图片说明

This post works perfectly, there was an issue present within the mail function to attach the file received by the API, the file properties are differently set and it failed to attach the file from bytearray... Fixed the call and added a throw exception within the API, Never return BadRequest(); in the catch section. error 400 will throw and not the standard error 500 server error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM