Search code examples
iosswift.net-corefetch-apiwebapi

In Swift (iOS app), what is the correct way to post data to my .net WebAPI which has [FromForm] parameters and uses autobinding?


Please Note: Not A Duplicate

Please read all of this, before you decide my question is a duplicate, because I've searched for answers and read numerous on SO, but none of them address the issue of having [FromForm] WebAPI binding.

I have the following WebAPI method in a Controller:

[HttpPost("SetScreenName")]
public ActionResult SetScreenName([FromForm] String guid, [FromForm] String screenName)

The user can simply pass in a guid and a screenName to set the screenName for the user profile.

I can call this easily from JavaScript fetch using the following code:

const formDataX = new FormData();
formDataX.append("guid","fakeguid-here");
formDataX.append("screenName", "newoneForTest");

fetch("https://localhost:7103/User/SetScreenName", {
  method: 'POST',
  body: formDataX,
})
  .then(response => response.json())
  .then(data => console.log(data));

Now, I need to know how to make a call to this same WebAPI method using Swift (in a iOS App / SwiftUI)

Here's What I've Tried

I've been trying to get thru this for a couple of days and would always get errors back from my WebAPI stating that one or both of the parameters (guid, screenName) were missing.

Here's a list of SO answers and snippets of code I've attempted to draw the answer from:

  1. swift url Session post request with parameters and image (Multipart Form-Data Requests )

  2. HTTP Request in Swift with POST method

Got the following code which I partially used, but still failed : Note: the failure was always that one or both params were missing.

let url = URL(string: "https://httpbin.org/post")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
  1. How can I build a URL with query parameters containing multiple values for the same key in Swift?

Tried following code but WebAPI would only recognized the first param (guid):

url.append(queryItems:  [URLQueryItem(name: "guid", value: "\(guid)"), URLQueryItem(name: "screenName", value: "\(screenName)")])
  1. How to make HTTP Post request with JSON body in Swift?

Tried to encode the params as JSON using code from that answer:

var outData = userData(uuid.uuidString.lowercased(), screenName)
var je = JSONEncoder()
  guard let jsonData = try? je.encode(outData) else{
     print ("encode FAILURE!")
     return false
}

Result data looked like: {"guid"="5c290f79-73a2-4bba-b34e-4d68c9d73ff7","screenName"="sallafootam"}

None of these solutions worked and my WebAPI would always indicate that one or more params (guid or screenName) were missing.

What is the definitive set up to post to my WebAPI method using Swift?


Solution

  • Here's the simplest setup that I finally discovered that works for my WebAPI with those [FromForm] parameters:

    request.httpMethod = "POST"
    var finalData = "guid=\(uuid.uuidString.lowercased())&screenName=\(screenName)"
    request.httpBody = finalData.data(using: String.Encoding.utf8)
    

    Notice that the values look like a normal QueryString, but you cannot add these to the queryString because they will not be bound on the WebAPI side.

    They have to be created, just as I show them in the snippet above and then added to the httpBody of the request.