[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