简体   繁体   English

jQuery修改后的“隐藏字段值”发布回服务器后为空

[英]JQuery modified Hidden Field Value is empty when posted back to the server

Summary: I have a web control that is dynamically added to the page. 摘要:我有一个动态添加到页面的Web控件。 The control has a HiddenField child control. 该控件有一个HiddenField子控件。 I am passing the control's ClientID to a jquery widget that is setting the value to a string (json converted to string). 我将控件的ClientID传递给将值设置为字符串(将json转换为字符串)的jquery小部件。 When the form is posted back to the server, the value of the HiddenField is a blank string. 将表单发布回服务器后,HiddenField的值为空白字符串。 I value is in the Request.Form[ UniqueID ] object. 我的值在Request.Form [ UniqueID ]对象中。 The value is making it back to the server. 该值将其返回给服务器。 The problem is that, I don't have access to the Request object when I need the value without modifying a lot of legacy code. 问题是,当我需要该值而无需修改大量旧代码时,就无法访​​问Request对象。

The strange thing is that the selectmany control is the one I am having a problem with, but it inherits from the SelectOne that is working properly. 奇怪的是,selectmany控件是我遇到的一个问题,但它继承自可以正常工作的SelectOne。 I think I am doing something wrong in the selectmany class because even if I try to push a value into the SelectOneHiddenValue it does not work ,but it works properly when the SelectOne uses it. 我认为我在selectmany类中做错了,因为即使我尝试将值推入SelectOneHiddenValue也不起作用,但是当SelectOne使用它时它可以正常工作。

SelectOne: SelectOne:

[ToolboxData("<{0}:SelectOne runat=server></{0}:SelectOne>")]
public class SelectOne : Panel, IControl,ISelectOne
{
    #region structure

    private readonly Panel _selectOneTextboxContainer = new Panel();
    protected readonly TextBox SelectOneTextbox = new TextBox();
    protected readonly HiddenField SelectOneHiddenValue = new HiddenField();
    private readonly Panel _selectOneDropdownImageContainer = new Panel();
    private readonly Image _selectOneDropDownImage = new Image();

    #endregion

    private readonly IList<LookupItem> _selectedItems = new List<LookupItem>();

    #region properties
    public IList<LookupItem> SelectedItems { get { return _selectedItems; } }

    public bool MultiSelect { get; set; }
    public DisplayOption Display { get; set; }
    public string Name { get; set; }

    [DefaultValue(0)]
    public int LookupValueOrgID
    {
        get
        {
            EnsureChildControls();
            return Convert.ToInt32(String.IsNullOrEmpty(SelectOneHiddenValue.Value) ? "0" : SelectOneHiddenValue.Value);
        }

        set
        {
            EnsureChildControls();
            SelectOneHiddenValue.Value = value.ToString();
        }
    }

    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("")]
    [Localizable(true)]
    public string Text
    {
        get
        {
            EnsureChildControls();
            return SelectOneTextbox.Text;
        }

        set
        {
            EnsureChildControls();
            SelectOneTextbox.Text = value;
        }
    }

    /// <summary>
    /// The minimum number of characters a user has to type before the autocompleter activates.
    /// </summary>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue(1)]
    [Localizable(true)]
    public int MinChars
    {
        get
        {
            int b = (ViewState["MinChars"] == null ? 1 : (int)ViewState["MinChars"]);
            return b;
        }
        set
        {
            ViewState["MinChars"] = value;
        }
    }

    /// <summary>
    /// The number of backend query results to store in cache. If set to 1 (the current result), no caching will happen. Must be >= 1.
    /// </summary>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue(10)]
    [Localizable(true)]
    public int CacheLength
    {
        get
        {
            int b = (ViewState["CacheLength"] == null ? 10 : (int)ViewState["CacheLength"]);
            return b;
        }
        set
        {
            ViewState["CacheLength"] = value;
        }
    }

    public string OuterMarkupClientID
    {
        get { return "SelectOne_Container" + ClientID; }
    }

    /// <summary>
    /// If true, target input text is appended to
    /// If false, target input text is replaced
    /// </summary>
    public bool AppendSelectedTextToInput { get; set; }

    public virtual string ContainerClass
    {
        get { return "SelectOneContainer"; }
    }

    #endregion

    #region constructor
    public SelectOne()
    {
        SetCssClasses();
    }

    #endregion
    #region lifecycle overrides

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        AddChildrenToControlCollection();
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        SetupClientEvents();
        ControlHelper.AddRequiredControl(this);

        var resourceName = string.Empty;

        var cs = Page.ClientScript;
        resourceName = "UI.Controls.resources.images.DropDownButton.gif";
        _selectOneDropDownImage.ImageUrl = cs.GetWebResourceUrl(GetType(), resourceName);

        SelectOneTextbox.Attributes.Add("lookupOrgID", LookupOrgID.ToString());
        SelectOneTextbox.Attributes.Add("cacheLength", CacheLength.ToString());
        SelectOneTextbox.Attributes.Add("service", Service);
        SelectOneTextbox.Attributes.Add("selectOneTextboxId", SelectOneTextbox.ClientID);
        SelectOneTextbox.Attributes.Add("selectOneHiddenValueId",SelectOneHiddenValue.ClientID);

    }

    #endregion

    #region private helpers
    private void SetCssClasses()
    {
        this.CssClass = ContainerClass + " AutocompleteContainer";
        _selectOneDropDownImage.CssClass = "SelectOneDropDownImage";
        SelectOneTextbox.CssClass = "SelectOneTextbox QuantifiTextBox";
        _selectOneTextboxContainer.CssClass = "SelectOneTextboxContainer";
        _selectOneDropdownImageContainer.CssClass = "SelectOneDropDownImageContainer";

    }

    private void SetupClientEvents()
    {
        ControlHelper.RegisterAutoCompleteScript(this);
        var resourceName = "UI.Controls.resources.scripts.SelectOne.js";

        string js;
        using (var sr = new StreamReader(GetType().Assembly.GetManifestResourceStream(resourceName)))
        {
            js = sr.ReadToEnd();
            sr.Close();
        }
        ClientScriptProxy.Current.RegisterStartupScript(this, typeof(SelectOne), "SelectOneJS", js, true);

        _selectOneDropDownImage.Attributes.Add("onclick", "SelectOne_ImageClick('" + SelectOneTextbox.ClientID + "');");
    }

    private void AddChildrenToControlCollection()
    {
        _selectOneTextboxContainer.Controls.Add(SelectOneTextbox);
        this.Controls.Add(_selectOneTextboxContainer);

        _selectOneDropdownImageContainer.Controls.Add(_selectOneDropDownImage);
        this.Controls.Add(_selectOneDropdownImageContainer);
        this.Controls.Add(SelectOneHiddenValue);
    }
    #endregion
}

Select Many: 选择许多:

[ToolboxData("<{0}:SelectMany runat=server></{0}:SelectMany>")]
public class SelectMany : SelectOne, ISelectMany
{
    #region structure

    private readonly Panel _selectedItemsPanel = new Panel();
    private readonly HiddenField _selectManyHiddenField = new HiddenField();

    public override string ContainerClass
    {
        get
        {
            return "SelectManyControlContainer";
        }
    }

    #endregion
    public SelectMany()
    {
        MultiSelect = true;
    }

    #region lifecycle overrides
    protected override void CreateChildControls()
    {
        base.CreateChildControls();


        _selectManyHiddenField.ID = "SelectedItemsHiddenValue";

        this.Controls.Add(_selectedItemsPanel);
        this.Controls.Add(_selectManyHiddenField);

        SelectOneTextbox.Attributes.Add("data-multiselect", MultiSelect.ToString());
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        var resourceName = "jquery.SelectedItemCollection.js";

        ClientScriptProxy.Current.RegisterClientScriptInclude(this, Page.ClientScript.GetWebResourceUrl(this.GetType(),resourceName));
        var serializer = new JavaScriptSerializer();
        var startupScript = String.Format("\n$('#{0}').each(function(){{" +
                                          "var selectedPlugin = $(this).SelectedItemCollection(" +
                                          "       {{" +
                                          "          itemData: {1}," +
                                          "          deleteImageUrl: '{2}'," +
                                          "          selectedTextId: '{3}', " +
                                          "          hiddenTextFieldId: '{4}' " +
                                          "       }});}});\n",
            this.ClientID, 
            serializer.Serialize(SelectedItems),
            GetDeleteImageUrl(),
            SelectOneTextbox.ClientID,
            _selectManyHiddenField.ClientID
            );
        ClientScriptProxy.Current.RegisterStartupScript(this,this.GetType(),"SelectedItemsJs_" + this.ClientID,startupScript,true);
    }
    #endregion

    #region public api
    public void BindForm()
    {
        EnsureChildControls();
        this.DataBind();
        var jsonString = _selectManyHiddenField.Value;

        SelectedItems.Clear();
        if (!jsonString.IsNullOrEmpty())
        {
            Json.Decode<IEnumerable<LookupItem>>(jsonString).ForEach(li => SelectedItems.Add(li));    
        }

    }
    #endregion

    private string GetDeleteImageUrl()
    {
        var cs = Page.ClientScript;
        const string resourceName = "UI.Controls.resources.images.close.gif";
        return cs.GetWebResourceUrl(this.GetType(), resourceName);
    }


}

Well, it was something stupid. 好吧,那真是愚蠢。 And it took me forever to find. 它花了我永远的时间。 Basically, don't misuse the EnsureChildControls() method. 基本上,不要滥用确保儿童控件()方法。 The base class was calling that before some of it's properties were accessed. 基类在调用某些属性之前就调用了它。 This called RecreateChildControls() after ViewState was restored, but before I could check the values. 在还原ViewState之后但在我无法检查值之前,这称为RecreateChildControls()。

To correct this, I added EnsureChildControls() in the OnInit override for both the base class and the derived class. 为了解决这个问题,我在OnInit覆盖中为基础类和派生类添加了SecureChildControls()。 That way, all my controls will be created properly and ViewState is restored after their creation. 这样,将正确创建我的所有控件,并在创建它们后还原ViewState。

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        EnsureChildControls();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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