简体   繁体   中英

Access Control in ObjectDataSource SelectMethod

Consider the following Webforms code using an ObjectDataSource to populate a GridView:

Default.aspx

<asp:GridView ID="GV" DataSourceID="ODS" runat="server"/>
<asp:ObjectDataSource ID="ODS"  TypeName="WebApplication.Default" SelectMethod="GetModels" runat="server" />
<asp:Label ID="Label" runat="server"/>

Default.aspx.cs

    private static readonly List<Model> Models; 

    static Default()
    {
        Models = new List<Model>
        {
            new Model {Id = 1, Name = "Foo"},
            new Model {Id = 2, Name = "Bar"},
            new Model {Id = 3, Name = "Foo"},
            new Model {Id = 4, Name = "Bar"}
        };
    }

    public List<Model> GetModels()
    {
        var listsizeCap = 3;
        var totalCount = Models.Count;
        if (totalCount > listsizeCap)
        {
            // Label is null!
            Label.Text = string.Format("The grid only shows the first {0} results of a total of {1}", listsizeCap, totalCount);
        }

        return Models.Take(listsizeCap).ToList();
    }

I need to cap the number of items returned by the datasource and show a Label how much items have been capped.

However, when I reach the GetModels method, Label is null.

Any idea how I can set a Control's value in an ObjectDataSource select method?

Are you talking about paging the data source? if this is the case you can just use the

EnablePaging="true"

SelectCountMethod=""

The method you declare here would return the total records that should be returned by this method. you need to write this method yourself but it should be identical to your select method. Then you can use:

MaximumRowsParameterName=""

StartRowIndexParameterName=""

These will be used by your ObjectDataSource's select method as it's last two parameters. Do not actually add them if you are declaring variables in the ObjectDataSource this will be passed automatically. Add the names you set here to your actual method deceleration. you will adjust your select code to page based on these values.

Edit: leaving items above for completeness. The answer to the question should be the following.

If you are using the paging methods of the ObjectDataSource then you should not try and change page elements from the select method. you should seperate this logic and rely on the ObjectDataSource's onSelected method. specifically you will be getting the return value of the SelectCountMethod you declared. What you can then do is add something like this to your code behind page.

public int recordsReturned;
public int recordCount;

protected void nameOfYourOnSelectedMethod(object sender, ObjectDataSourceStatusEventArgs e)
{
// check if this call is from the Select or SelectCount method
if (e.ExecutingSelectCount) {
  // logic here will be used for setting the label
  recordCount = e.ReturnValue;
  Label.Text = "The grid only shows the first " + recordsReturned.ToString()  + " results of a total of " + recordCount.ToString();
}
else {
  // logic here is to get the amount of records returned
  // you just want to save the value here
  recordsReturned = e.ReturnValue.Count();
}

have not tried out the code myself but it should work.

For all ASP.NET is concerned, the TypeName attribute on ObjectDataSource refers to a simple POCO. In my case it happened to be the Page class. Anyway, there isn't any Page hardwiring done when ASP.NET calls GetModels so other controls, such as Label are never initialized behind the scenes.

I found a solution by adding temporarily state on HttpContext.Current.Items .

GetModels then becomes:

public List<Model> GetModels()
{
    var listsizeCap = 3;
    var totalCount = Models.Count;
    if (totalCount > listsizeCap)
    {
        HttpContext.Current.Items["LabelToSet"] = string.Format("The grid only shows the first {0} results of a total of {1}", listsizeCap, totalCount);
    }

    return Models.Take(listsizeCap).ToList();
}

Default.aspx is updated with a OnDataBound event:

<asp:GridView ID="GV" DataSourceID="ODS" OnDataBound="GV_DataBound" runat="server"/>

Which reads the value back from the HttpContext and assigns it to the Label :

protected void GV_DataBound(object sender, EventArgs e)
{
    Label.Text = HttpContext.Current.Items["LabelToSet"].ToString();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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