skip to Main Content

My website can create a link token with Plaid, but whenever I attempt to send this data back to the server, some of the data is missing.

Heres’ my .csthml file

    @section scripts_upper
{
    <!-- Include the Plaid Link initialize script on each page of your site. -->
    <!-- It should always be loaded directly from https://cdn.plaid.com, rather -->
    <!-- than included in a bundle or hosted yourself. -->
    <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
}

@model SS.PFS.WebApp.Models.PlaidLinkResults

@{
    ViewBag.Title = "Link";
}
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <h2>Link</h2>
    <p>
        LinkToken:  @ViewBag.LinkToken
    </p>
    <p>
        Accesstoken:  @ViewBag.Accesstoken
    </p>

    <div class="col-md-offset-2 col-md-10">
        <input type="button" value="Link" onclick="launchPlaid()" class="btn btn-default" />
    </div>


    <label>Plaid Public Token</label>
    <br>
    <p id='plaidToken'></p>
    <BR>
    <label>MetaData</label>
    <br>
<textarea id='plaidMetadata2' rows='30' cols='100'></textarea>

}

@section scripts
{

    <script>

        function launchPlaid() {
            const handler = Plaid.create({
                //token: document.getElementById('linkToken').value,
                token:  '@ViewBag.LinkToken',
                // The onSuccess() function of the Plaid plugin will return a public
                // token and metadata object to your code. Please use our API to send
                // us the public token, and we will query the routing number and account
                // number of the bank account from Plaid and store it securely on our systems.
                onSuccess: (public_token, metadata) => {
                    document.getElementById('plaidToken').innerHTML = public_token;
                    document.getElementById('plaidMetadata2').value = JSON.stringify(metadata, null, 2);
                    //testPost(JSON.stringify(metadata, null, 2));
                   // testPost(metadata);
                    testPost(JSON.stringify(metadata));
                    return true;
                },
                onLoad: () => {  },
                onExit: (err, metadata) => {
                    document.getElementById('plaidToken').innerHTML = err;
                    document.getElementById('plaidMetadata2').value = JSON.stringify(metadata, null, 2);
                },
                onEvent: (eventName, metadata) => {  },
                receivedRedirectUri: null,
            });
            // Calling open() will display the "Institution Select" view to your user,
            // starting the Link flow.
            handler.open();
        }


        function testPost(valueToPost) {

            $.ajax({
                type: "POST",
                url: "/BankAccount/Link",
                data: '{ results: ' + valueToPost+ '}',
             //  data: valueToPost,
                //contentType: "application/json; charset=utf-8",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    alert("Hello: " + response.Name + " .nCurrent Date and Time: " + response.DateTime);
                },
                failure: function (response) {
                    alert('failure:  ' + response.responseText);
                },
                error: function (response) {
                    //alert('error:  ' + response.responseText);
                    //document.getElementById('plaidMetadata2').value = response.responseText;
                    document.getElementById('plaidMetadata2').value =  valueToPost;
                }
            });
        }
    </script>
}

Here’s the /BankAccount/Link controller/action

[HttpPost]
    public async Task<ActionResult> Link(Models.PlaidLinkResults results)
    {
        var resultsetToSaveAsLinkedAccounts = results;
        return View("Index");
    }

I can see data filled in as the final result is displayed in plaidMetadata2. it contains values for Accounts, but properties like Institution->Id, LinkSessionId, and PublicToken are empty. Accounts has some data too.

Here’s an example of the data from the browser debugging tools
enter image description here

Screenshot of data on server

Here’s the PlaidLinkResults model

using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace SS.PFS.WebApp.Models
{
    public class PlaidLinkResults
    {
        [JsonProperty("institution") ]
        public Acklann.Plaid.Entity.Institution Institution { get; set; }

        public Acklann.Plaid.Entity.Account Account { get; set; }

        public string AccountId { get; set; }

        public List<Acklann.Plaid.Entity.Account> Accounts { get; set; }

        [JsonProperty("link_session_id")]
        public string LinkSessionId { get; set; }

        [JsonProperty("public_token")]
        public string PublicToken { get; set; }
    }
}

Here’s the code for the institution model

using Acklann.Plaid.Institution;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Acklann.Plaid.Entity
{
    /// <summary>
    /// Represents a banking institution.
    /// </summary>
    public class Institution
    {
        /// <summary>
        /// Gets or sets the identifier.
        /// </summary>
        /// <value>The identifier.</value>
        [JsonProperty("institution_id")]
        public string Id { get; set; }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        [JsonProperty("name")]
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance has Multi-Factor Authentication.
        /// </summary>
        /// <value><c>true</c> if this instance has Multi-Factor Authentication; otherwise, <c>false</c>.</value>
        [JsonProperty("has_mfa")]
        public bool HasMfa { get; set; }

        /// <summary>
        /// Gets or sets the Multi-Factor Authentication selections.
        /// </summary>
        /// <value>The mfa selections.</value>
        [JsonProperty("mfa")]
        public string[] MfaSelections { get; set; }

        [JsonProperty("mfa_code_type")]
        public string MfaType { get; set; }

        /// <summary>
        /// Gets or sets the hexadecimal representation of the primary color used by the institution.
        /// </summary>
        [JsonProperty("primary_color")]
        public string PrimaryColor { get; set; }

        /// <summary>
        /// Gets or sets the Base64 encoded representation of the institution's logo.
        /// </summary>
        [JsonProperty("logo")]
        public string Logo { get; set; }

        /// <summary>
        /// Gets or sets the URL for the institution's website.
        /// </summary>
        /// <value>
        /// The URL.
        /// </value>
        [JsonProperty("url")]
        public string Url { get; set; }

        /// <summary>
        /// Gets or sets the credentials.
        /// </summary>
        /// <value>The credentials.</value>
        [JsonProperty("credentials")]
        public Credential[] Credentials { get; set; }

        /// <summary>
        /// Gets or sets the products.
        /// </summary>
        /// <value>The products.</value>
        [JsonProperty("products")]
        public string[] Products { get; set; }

        /// <summary>
        /// Gets or sets the country codes using the ISO-3166-1 alpha-2 country code standard.
        /// </summary>
        /// <value>
        /// The countries.
        /// </value>
        [JsonProperty("country_codes")]
        public string[] Countries { get; set; }

        /// <summary>
        /// Gets or sets the information about the institution's current status.
        /// </summary>
        [JsonProperty("status")]
        public StatusSchema Status { get; set; }

        /// <summary>
        /// Represents an <see cref="Institution"/> login credentials.
        /// </summary>
        public struct Credential
        {
            /// <summary>
            /// Gets or sets the label.
            /// </summary>
            /// <value>The label.</value>
            [JsonProperty("label")]
            public string Label { get; set; }

            /// <summary>
            /// Gets or sets the name.
            /// </summary>
            /// <value>The name.</value>
            [JsonProperty("name")]
            public string Name { get; set; }

            /// <summary>
            /// Gets or sets the type of the data.
            /// </summary>
            /// <value>The type of the data.</value>
            [JsonProperty("type")]
            public string DataType { get; set; }
        }

        public class StatusSchema
        {
            /// <summary>
            /// Gets or sets status information regarding Item adds via Link.
            /// </summary>
            [JsonProperty("item_logins")]
            public InstitutionStatus ItemLogin { get; set; }

            /// <summary>
            /// Gets or sets the status information regarding transactions updates.
            /// </summary>
            [JsonProperty("transactions_updates")]
            public InstitutionStatus Transactions { get; set; }

            /// <summary>
            /// Gets or sets the status information regarding Auth requests..
            /// </summary>
            /// <value>
            /// The authentication.
            /// </value>
            [JsonProperty("auth")]
            public InstitutionStatus Auth { get; set; }

            /// <summary>
            /// Gets or sets the status information regarding Balance requests.
            /// </summary>
            /// <value>
            /// The balance.
            /// </value>
            [JsonProperty("balacne")]
            public InstitutionStatus Balance { get; set; }

            /// <summary>
            /// Gets or sets the status information regarding Identity requests.
            /// </summary>
            [JsonProperty("identity")]
            public InstitutionStatus Identity { get; set; }
        }
    }
}

2

Answers


  1. Most times this happens is because of malformed data being sent.

    Noticed some issues with how you are formatting the data to be sent which leads to your JSON not being well formatted.

    Note how the results field has no quotes

    because you try to build the string yourself

    //...
    
    data: '{ results: ' + valueToPost+ '}',
    
    //...
    

    The model binder is then tasked with trying to infer the data needed from the malformed payload and map them to the model.

    I would first suggest just passing the metadata to testPost function as is

    //...
    onSuccess: (public_token, metadata) => {
    
      //...
    
      testPost(metadata);
      return true;
    },
    //...
    

    and let that function handle the formatting.

    function testPost(valueToPost) {
        var data = { results : valueToPost }; //creating payload object
        $.ajax({
            type: "POST",
            url: "/BankAccount/Link",
            data: JSON.stringify(data), //formatting to JSON here
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (response) {
                alert("Hello: " + response.Name + " .nCurrent Date and Time: " + response.DateTime);
            },
            failure: function (response) {
                alert('failure:  ' + response.responseText);
            },
            error: function (response) {
                //alert('error:  ' + response.responseText);
                //document.getElementById('plaidMetadata2').value = response.responseText;
                document.getElementById('plaidMetadata2').value =  valueToPost;
            }
        });
    }
    

    The action should also explicitly tell the model binder where to look for the data

    [HttpPost]
    public ActionResult Link([FromBody]Models.PlaidLinkResults results) {
        var resultsetToSaveAsLinkedAccounts = results;
        return View("Index");
    }
    

    So that it does not have to infer the data from one of the possible sources

    Login or Signup to reply.
  2. Okay maybe I’m crazy but reading the Plaid HTML comment:

    // The onSuccess() function of the Plaid plugin will return a public token and metadata object to your code. Please use our API to send us the public token, and we will query the routing number and account number of the bank account from Plaid and store it securely on our systems.

    Now when I look at your onSuccess code:

    document.getElementById('plaidToken').innerHTML = public_token;
    document.getElementById('plaidMetadata2').value = JSON.stringify(metadata, null, 2);
    //testPost(JSON.stringify(metadata, null, 2));
    // testPost(metadata);
    testPost(JSON.stringify(metadata));
    

    You get both the token and metadata, but it looks to me like you keep trying to send them the metadata. They only ask for the public token. Why send metadata? Did I miss something?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search