RemotePost

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
Hace 12 años
При написании плагина потребовалось отправить на сервер форму, в которой содержалось несколько контролов input с одинаковым аттрибутом name, но разными значениями. Пример:

<form method="post" action="https://merchant.w1.ru/checkout/default.aspx">
  <input name="WMI_MERCHANT_ID"    value="123456789012"/>
  <input name="WMI_PAYMENT_AMOUNT" value="100.00"/>
  <input name="WMI_CURRENCY_ID"    value="643"/>
  <input name="WMI_DESCRIPTION"    value="Оплата демонстрационного заказа"/>
  <input name="WMI_PTENABLED"      value="WebMoneyRUB"/>
  <input name="WMI_PTENABLED"      value="WebMoneyUSD"/>
  <input name="WMI_PTENABLED"      value="WebMoneyEUR"/>
  <input name="WMI_PTENABLED"      value="WebMoneyUAH"/>
  <input name="WMI_PTENABLED"      value="WebMoneyGLD"/>
  <input name="WMI_SUCCESS_URL"    value="https://myshop.ru/w1/paid.php"/>
  <input name="WMI_FAIL_URL"       value="https://myshop.ru/w1/fail.php"/>
  <input type="submit"/>
</form>


Для отправки хотел воспользоваться классом Nop.Web.Framework.RemotePost и выяснилось, что вместо нескольких строк он генерит одну:
<input name="WMI_PTENABLED" value="WebMoneyRUB,WebMoneyUSD,WebMoneyEUR,WebMoneyUAH,WebMoneyGLD"/>


Предлагаю заменить код:
for (int i = 0; i < _inputValues.Keys.Count; i++)
                _httpContext.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", HttpUtility.HtmlEncode(_inputValues.Keys[i]), HttpUtility.HtmlEncode(_inputValues[_inputValues.Keys[i]])));


на что-то типа

      foreach (string key in _inputValues.Keys)
      {
        foreach (string value in _inputValues[key].Split(new char[] { ',' }))
          _httpContext.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", HttpUtility.HtmlEncode(key), HttpUtility.HtmlEncode(value)));
      }
Hace 12 años
Спасибо за предложение. Смотрите changeset 2dcf25bd0253
Hace 12 años
Прошу прощения, я привёл не корректный пример, каюсь. Не учёл, что значения могут содержать знак запятой, поэтому Split использовать нельзя.
И ещё, у тэга <form> есть полезный аттрибут "accept-charset"...
Предлагаю следующий код для RemotePost.cs:

using System;
using System.Collections.Specialized;
using System.Web;
using Nop.Core.Infrastructure;

namespace Nop.Web.Framework
{
  /// <summary>
  /// Represents a RemotePost helper class
  /// </summary>
  public partial class RemotePost
  {
    private readonly HttpContextBase _httpContext;
    private readonly NameValueCollection _inputValues;

    /// <summary>
    /// Gets or sets a remote URL
    /// </summary>
    public string Url { get; set; }

    /// <summary>
    /// Gets or sets a method
    /// </summary>
    public string Method { get; set; }

    /// <summary>
    /// Gets or sets a form name
    /// </summary>
    public string FormName { get; set; }

    /// <summary>
    /// Gets or sets a form character-sets the server can handle for form-data.
    /// </summary>
    public string AcceptCharset { get; set; }

    /// <summary>
    /// A value indicating whether we should create a new "input" HTML element for each value (in case if there are more than one) for the same "name" attributes.
    /// </summary>
    public bool NewInputForEachValue { get; set; }

    public NameValueCollection Params
    {
      get
      {
        return _inputValues;
      }
    }

    /// <summary>
    /// Creates a new instance of the RemotePost class
    /// </summary>
    public RemotePost()
    {
      _inputValues = new NameValueCollection();
      Url = "http://www.someurl.com";
      Method = "POST";
      FormName = "formName";
      AcceptCharset = String.Empty;
      //TODO inject
      _httpContext = EngineContext.Current.Resolve<HttpContextBase>();
    }

    /// <summary>
    /// Adds the specified key and value to the dictionary (to be posted).
    /// </summary>
    /// <param name="name">The key of the element to add</param>
    /// <param name="value">The value of the element to add.</param>
    public void Add(string name, string value)
    {
      _inputValues.Add(name, value);
    }

    /// <summary>
    /// Post
    /// </summary>
    public void Post()
    {
      _httpContext.Response.Clear();
      _httpContext.Response.Write("<html><head>");
      _httpContext.Response.Write(string.Format("</head><body onload=\"document.{0}.submit()\">", FormName));
      _httpContext.Response.Write(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\" accept-charset=\"{3}\">", FormName, Method, Url, AcceptCharset));
      
      if (String.IsNullOrEmpty(AcceptCharset))
        _httpContext.Response.Write(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\">", FormName, Method, Url));
      else
        _httpContext.Response.Write(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\" accept-charset=\"{3}\">", FormName, Method, Url, AcceptCharset));

      if (NewInputForEachValue)
      {
        foreach (string key in _inputValues.Keys)
        {
          string[] values = _inputValues.GetValues(key);
          foreach (string value in values)
            _httpContext.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", HttpUtility.HtmlEncode(key), HttpUtility.HtmlEncode(value)));
        }
      }
      else
      {
        for (int i = 0; i < _inputValues.Keys.Count; i++)
          _httpContext.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", HttpUtility.HtmlEncode(_inputValues.Keys[i]), HttpUtility.HtmlEncode(_inputValues[_inputValues.Keys[i]])));
      }
      _httpContext.Response.Write("</form>");
      _httpContext.Response.Write("</body></html>");
      _httpContext.Response.End();
    }
  }
}
Hace 12 años
Спасибо. Ктати, насколько я знаю accept-charset не поддерживается IE
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.