为啥通过 jQuery Ajax 将 Plaid 链接结果发布到 ASP.NET MVC 控制器时缺少属性数据?

Posted

技术标签:

【中文标题】为啥通过 jQuery Ajax 将 Plaid 链接结果发布到 ASP.NET MVC 控制器时缺少属性数据?【英文标题】:Why is this POSTing of Plaid link results to ASP.NET MVC controller via jQuery Ajax missing property data?为什么通过 jQuery Ajax 将 Plaid 链接结果发布到 ASP.NET MVC 控制器时缺少属性数据? 【发布时间】:2021-12-15 17:53:47 【问题描述】:

我的网站可以使用 Plaid 创建链接令牌,但是每当我尝试将此数据发送回服务器时,都会丢失一些数据。

这是我的 .csthml 文件

    @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>

这里是 /BankAccount/Link 控制器/动作

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

我可以看到填充的数据,因为最终结果显示在 plaidMetadata2 中。它包含 Accounts 的值,但机构->Id、LinkSessionId 和 PublicToken 等属性为空。帐户也有一些数据。

这是来自浏览器调试工具的数据示例

这是 PlaidLinkResults 模型

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; 
    

这是机构模型的代码

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; 
        
    

【问题讨论】:

***.com/questions/24897579/… 可以帮忙 【参考方案1】:

大多数情况下发生这种情况是因为发送了格式错误的数据。

注意到您如何格式化要发送的数据的一些问题导致您的 JSON 格式不正确。

注意results 字段没有引号

因为你尝试自己构建字符串

//...

data: ' results: ' + valueToPost+ '',

//...

然后模型绑定器的任务是尝试从格式错误的有效负载中推断出所需的数据并将它们映射到模型。

我首先建议将元数据按原样传递给testPost 函数

//...
onSuccess: (public_token, metadata) => 

  //...

  testPost(metadata);
  return true;
,
//...

并让该函数处理格式。

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;
        
    );

该操作还应该明确告诉模型绑定器在哪里查找数据

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

这样它就不必从可能的来源之一推断数据

【讨论】:

这一切都说得通...我试过了,但得到了相同的结果。打印出文本框中发布的数据,它看起来像格式完美的 json 数据。这让我相信它是某种控制器。【参考方案2】:

好吧,也许我疯了,但请阅读 Plaid HTML 评论:

// Plaid 插件的 onSuccess() 函数将向您的代码返回一个公共令牌和元数据对象。请使用我们的 API向我们发送公共令牌,我们将从 Plaid 查询银行账户的路由号码和帐号并将其安全地存储在我们的系统中。

现在,当我查看您的 onSuccess 代码时:

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));

您同时获得了令牌和元数据,但在我看来,您一直在尝试向他们发送元数据。 他们只要求公共令牌。 为什么要发送元数据?我错过了什么吗?

【讨论】:

我还没有到发送 Plaid 公共令牌的地步。这是我在进一步使用 Plaid 之前存储公共令牌的步骤。

以上是关于为啥通过 jQuery Ajax 将 Plaid 链接结果发布到 ASP.NET MVC 控制器时缺少属性数据?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 IE 10 拒绝通过 jQuery $.ajax 发送 POST 数据

为啥从 Psql 通过 Swift (Vapor) 到通过 Ajax 的 JQuery 的日期落后了 31 年?

为啥我通过 jquery ajax 和 codeigniter 得到验证错误?

为啥 jQuery 的 .ajax() 方法不发送我的会话 cookie?

jQuery.ajax为啥不能实现return值

为啥jQuery的ajax会自动运行脚本?