在asp:net Search App

时间:2018-05-13 18:56:18

标签: asp.net gridview active-directory

我已经设置了一个WebApplication来搜索我们组织的Active Directory。 Query(动态SQL包装OpenQuery)也返回thumpnailPhoto的十六进制数据。

当我显示图像时,我在所有显示的图片上获得40%的成功。 "坏"从顶部开始,前15%通常罚款,然后用黑色条纹停止。有时会有条纹重复的图片数据...有些个人资料图片根本没有显示,而有些则完美无缺。必须有不同的图像格式,但无法访问这些图像的存储位置,我不会再进一步​​了。

这就是我的意思: 我将查询中的数据绑定到GridView。

protected void FillGrid(Object sender, EventArgs e)
{
    SqlConnection objConn = new SqlConnection("Data Source=XXXXXXXXXX");
    SqlDataAdapter adapter = new SqlDataAdapter();
    SqlCommand objCommand = new SqlCommand(@"declare @SQL nvarchar(4000)
                                             declare @Asterisc nvarchar(1)
                                             declare @Sub nvarchar(12)
                                             set @SearchName = CASE WHEN @SearchName = '' THEN '*' ELSE @SearchName END
                                             set @SearchSurename = CASE WHEN @SearchSurename = '' THEN '*' ELSE @SearchSurename END
                                             set @Asterisc = '*'
                                             set @Sub = CASE WHEN @Subsidiary = '*' THEN '' ELSE (@Subsidiary+', OU=') END
                                             set @SQL ='SELECT TOP (100) PERCENT samAccountName AS UserAccount, givenName AS FirstName, sn AS LastName, department, title AS Position, 
                                                               physicaldeliveryofficename AS Office, extensionAttribute1 AS PersonnelID, initials, mail AS email, telephonenumber AS Phone, extensionattribute5 AS Extension, 
                                                               mobile, extensionattribute3 AS MobileExt, thumbnailPhoto
                                                        FROM OPENQUERY(ADSI, ''SELECT samAccountName, givenName, sn, legacyExchangeDN, department, title, physicaldeliveryofficename, extensionAttribute1, distinguishedName, initials,
                                                                                      mail, telephonenumber, extensionattribute5, mobile, extensionattribute3, thumbnailPhoto
                                                                               FROM ''''LDAP://OU=' + @Sub + 'XXXX, DC=XXXX,DC=XXXX,DC=XXXX''''
                                                                               WHERE objectClass=''''Person'''' AND objectClass = ''''User'''' AND givenName = ''''' + @SearchName + ''''' AND samAccountName = ''''' + @SearchSurename + ''''' AND extensionAttribute1 = ''''' + @Asterisc + ''''' '') AS AD_Users
                                                        ORDER BY UserAccount'
                                                        exec (@SQL)", objConn);
    objCommand.Parameters.Add("@SearchName", SqlDbType.NVarChar).Value = TextBoxSearchName.Text;
    objCommand.Parameters.Add("@SearchSurename", SqlDbType.NVarChar).Value = TextBoxSearchSureName.Text;
    objCommand.Parameters.Add("@Subsidiary", SqlDbType.NVarChar).Value = DDSubsidiary.Text;
    DataTable t = new DataTable();
    adapter.SelectCommand = objCommand;
    objConn.Open();
    adapter.Fill(t);
    objConn.Close();
    GridView.DataSource = t;
    GridView.DataBind();
}

然后在RowDataBound事件期间,我像这样编码数据并将该数据绑定到asp:image控件:

protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        DataRowView dr = (DataRowView)e.Row.DataItem;
        if(!String.IsNullOrEmpty(Convert.ToString(dr["thumbnailPhoto"])))
        {
            string imageUrl = "data:image/jpg;base64," + Convert.ToBase64String((byte[])dr["thumbnailPhoto"]);
            (e.Row.FindControl("Image1") as Image).ImageUrl = imageUrl;
        }
    }
}

我在这里遇到什么问题以及如何处理它?<​​/ p>

我刚刚发现那些部分显示或带有条纹的图片都是以600x600格式存储的图片,而好的图片则是96x96格式。这使我怀疑通过SQL检索其中的十六进制格式的thumbprintPhoto时会出现问题。

正如加布里埃尔所说,我试图使用DirectorySearcher。 thumbprintPhoto显示正确,但检索44个AD条目花了我超过10秒:这是我的代码

    protected void SearchAD(object sender, EventArgs e)
    {
        string Name = TextBoxSearchFirstName.Text;
        Name = Name.Replace("*", "") + "*";
        DirectorySearcher dsSearcher = new DirectorySearcher();
        dsSearcher.Filter = "(&(objectClass=user) (sn=" + Name + "))";
        results = dsSearcher.FindAll();

        DataTable t = new DataTable("ActiveDir");
        t.Columns.Add(new DataColumn("SecondName", System.Type.GetType("System.String")));
        t.Columns.Add(new DataColumn("FirstName", System.Type.GetType("System.String")));
        t.Columns.Add(new DataColumn("UserID", System.Type.GetType("System.String")));
        t.Columns.Add(new DataColumn("data", System.Type.GetType("System.Byte[]")));           

        if (results != null)
        {
            foreach (SearchResult searchResult in results)
            {
                DataRow myRow;
                myRow = t.NewRow();
                myRow[0] = searchResult.GetDirectoryEntry().Properties["sn"].Value;
                myRow[1] = searchResult.GetDirectoryEntry().Properties["givenName"].Value;
                myRow[2] = searchResult.GetDirectoryEntry().Properties["samAccountName"].Value;
                myRow[3] = searchResult.GetDirectoryEntry().Properties["thumbnailPhoto"].Value;
                t.Rows.Add(myRow);
            }
        }
        GridView1.DataSource = t;
        GridView1.DataBind();
    }

解决:Gabriel调整了AD搜索代码,现在它比SQL查询更快。 为了在不使用处理程序的情况下显示AD Thumnail Profil图片,请在GridViews OnRowDataBound事件期间进行解码:

    protected void OnRowDataBoundAdUser(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            DataRowView dr = (DataRowView)e.Row.DataItem;
            if (!String.IsNullOrEmpty(Convert.ToString(dr["data"])))
            {
                byte[] data = dr["data"] as byte[];
                MemoryStream s = new MemoryStream(data);
                byte[] imageBytes = s.ToArray();
                string base64String = Convert.ToBase64String(imageBytes);
                string imageUrl = "data:image/jpg;base64," + base64String;
                (e.Row.FindControl("Image1") as System.Web.UI.WebControls.Image).ImageUrl = imageUrl;
            }
        }
    }

1 个答案:

答案 0 :(得分:2)

我知道为什么这么长时间。 DirectorySearcherDirectoryEntry可能有点偷偷摸摸地与AD达到了多少次。你需要的网络请求比你需要的要多得多。

在您的代码中,您将前往AD进行一次搜索。然后,对于每个结果,您使用的是GetDirectoryEntry()。首次使用DirectoryEntry时,Properties会再次转到AD。更糟糕的是,只要您使用Properties,它就会下载具有值的每个属性,即使您实际上只使用了其中的4个。这是一大堆无用的网络流量。

您可以在搜索结果中使用Properties集合来避免这种情况,搜索结果中已包含所有属性(默认情况下,它会获取具有值的每个属性)。

但是你可以做得更好:如果你设置PropertiesToLoad DirectorySearcher属性,那么它只会返回你想要使用的值。这样,您就可以获得所需的一切网络请求,您想要的内容。

protected void SearchAD(object sender, EventArgs e)
{
    string Name = TextBoxSearchFirstName.Text;
    Name = Name.Replace("*", "") + "*";
    var dsSearcher = new DirectorySearcher {
        Filter = "(&(objectClass=user) (sn=" + Name + "))"
    };
    dsSearcher.PropertiesToLoad.Add("sn");
    dsSearcher.PropertiesToLoad.Add("givenName");
    dsSearcher.PropertiesToLoad.Add("samAccountName");
    dsSearcher.PropertiesToLoad.Add("thumbnailPhoto");

    using (var results = dsSearcher.FindAll()) {
        var t = new DataTable("ActiveDir");
        t.Columns.Add(new DataColumn("SecondName", typeof(string)));
        t.Columns.Add(new DataColumn("FirstName", typeof(string)));
        t.Columns.Add(new DataColumn("UserID", typeof(string)));
        t.Columns.Add(new DataColumn("data", typeof(byte[])));

        foreach (SearchResult searchResult in results) {
            var myRow = t.NewRow();
            myRow[0] = searchResult.Properties.Contains("sn") ? searchResult.Properties["sn"][0] : null;
            myRow[1] = searchResult.Properties.Contains("givenName") ? searchResult.Properties["givenName"][0] : null;
            myRow[2] = searchResult.Properties.Contains("samAccountName") ? searchResult.Properties["samAccountName"][0] : null;
            myRow[3] = searchResult.Properties.Contains("thumbnailPhoto") ? searchResult.Properties["thumbnailPhoto"][0] : null;
            t.Rows.Add(myRow);
        }
    }
    GridView1.DataSource = t;
    GridView1.DataBind();
}

一些注意事项:

需要调用Contains,因为如果该属性为空,则根本不存在Properties集合中。

搜索结果将所有内容作为数组返回,无论它是否在AD中。因此,每个属性都需要[0]

您会注意到我在搜索结果周围添加了using语句。这是防止内存泄漏所必需的,according to the documentation of FindAll()