[Mono-aspnet-list] How to show dynamic data from npgsql in WebGrid
    Andrus 
    kobruleht2 at hot.ee
       
    Sat Jul 26 09:30:01 UTC 2014
    
    
  
In Mono ASP .NET MVC4 application, WebGrid shows npgsql dynamic data last row values in every row.
In Mono code below returns
    ?column?
    B
    B
How to force it to return proper result?
If running in windows under Microsoft .NET it returns proper result:
    ?column?
    A
    B
Controller:
        public ActionResult Test()
        {
            var data = TestData();
            return View("ReportData", new ReportDataViewModel(data, ""));
        }
        IEnumerable<dynamic> TestData()
        {
            using (var connection = new NpgsqlConnection(ConnectionString()))
            {
                connection.Open();
                DbCommand command = (DbCommand)connection.CreateCommand();
                command.CommandText = "select 'A' union select 'B'";
                using (command)
                {
                    IEnumerable<string> columnNames = null;
                    using (DbDataReader reader = command.ExecuteReader())
                    {
                        foreach (DbDataRecord record in reader)
                        {
                            if (columnNames == null)
                                columnNames = GetColumnNames(record);
                            yield return new CustomDynamicRecord(columnNames, record);
                        }
                    }
                }
            }
        }
        static IEnumerable<string> GetColumnNames(DbDataRecord record)
        {
            for (int i = 0; i < record.FieldCount; i++)
            {
                yield return record.GetName(i);
            }
        }
        static string ConnectionString()
        {
            NpgsqlConnectionStringBuilder csb = new NpgsqlConnectionStringBuilder()
            {
                SearchPath = "public",
                Host = "localhost",
                Database = "eeva",
                UserName = "postgres",
                Password = "secret"
            };
            return csb.ConnectionString;
        }
CustomDynamicRecord class is copied from ASP.NET source code with minor modifications:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Dynamic;
    using System.Globalization;
    using System.Linq;
    using WebMatrix.Data.Resources;
    public sealed class CustomDynamicRecord : DynamicObject, ICustomTypeDescriptor
    {
        public CustomDynamicRecord(IEnumerable<string> columnNames, IDataRecord record)
        {
            Columns = columnNames.ToList();
            Record = record;
        }
        public IList<string> Columns { get; private set; }
        private IDataRecord Record { get; set; }
        public object this[string name]
        {
            get
            {
                return GetValue(Record[name]);
            }
        }
        public object this[int index]
        {
            get
            {
                return GetValue(Record[index]);
            }
        }
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = this[binder.Name];
            return true;
        }
        static object GetValue(object value)
        {
            if (DBNull.Value == value || value == null)
              return null;
           return value;
        }
        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return Columns;
        }
        private void VerifyColumn(string name)
        {
            if (!Columns.Contains(name, StringComparer.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentCulture,
                                  "Invalid Column Name " + name));
            }
        }
        AttributeCollection ICustomTypeDescriptor.GetAttributes()
        {
            return AttributeCollection.Empty;
        }
        string ICustomTypeDescriptor.GetClassName()
        {
            return null;
        }
        string ICustomTypeDescriptor.GetComponentName()
        {
            return null;
        }
        TypeConverter ICustomTypeDescriptor.GetConverter()
        {
            return null;
        }
        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        {
            return null;
        }
        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
        {
            return null;
        }
        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
        {
            return null;
        }
        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        {
            return EventDescriptorCollection.Empty;
        }
        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return EventDescriptorCollection.Empty;
        }
        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
        {
            return ((ICustomTypeDescriptor)this).GetProperties();
        }
        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
        {
            var properties = from columnName in Columns
                             let columnIndex = Record.GetOrdinal(columnName)
                             let type = Record.GetFieldType(columnIndex)
                             select new DynamicPropertyDescriptor(columnName, type);
            return new PropertyDescriptorCollection(properties.ToArray(), readOnly: true);
        }
        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }
        private class DynamicPropertyDescriptor : PropertyDescriptor
        {
            private static readonly Attribute[] _empty = new Attribute[0];
            private readonly Type _type;
            public DynamicPropertyDescriptor(string name, Type type)
                : base(name, _empty)
            {
                _type = type;
            }
            public override Type ComponentType
            {
                get { return typeof(EevaDynamicRecord); }
            }
            public override bool IsReadOnly
            {
                get { return true; }
            }
            public override Type PropertyType
            {
                get { return _type; }
            }
            public override bool CanResetValue(object component)
            {
                return false;
            }
            public override object GetValue(object component)
            {
                EevaDynamicRecord record = component as EevaDynamicRecord;
                // REVIEW: Should we throw if the wrong object was passed in?
                if (record != null)
                {
                    return record[Name];
                }
                return null;
            }
            public override void ResetValue(object component)
            {
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentCulture,
                                  "DataResources.RecordIsReadOnly", Name));
            }
            public override void SetValue(object component, object value)
            {
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentCulture,
                                  "DataResources.RecordIsReadOnly", Name));
            }
            public override bool ShouldSerializeValue(object component)
            {
                return false;
            }
        }
    }
View:
    @inherits ViewBase<ViewModels.ReportDataViewModel>
    @using System.Web.Helpers
    
    @{ Layout = null;
     var gd = new WebGrid(source: Model.Rows, canSort: false , rowsPerPage:100 );
    }
    
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
      @gd.GetHtml()
    </body>
    </html>
Model:
    namespace ViewModels
    {
        public class ReportDataViewModel : ViewModelBase
        {
            public IEnumerable<dynamic> Rows { get; set; }
     
            public ReportDataViewModel(IEnumerable<dynamic> rows)
            {
                Rows = rows;
            }
        }
    }
Posted also in http://stackoverflow.com/questions/24965486/how-to-show-dynamic-data-using-npgsql-in-mono-in-webgrid
Andrus.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ximian.com/pipermail/mono-aspnet-list/attachments/20140726/7a1abec5/attachment-0001.html>
    
    
More information about the Mono-aspnet-list
mailing list