Calling variables with string interpolation in Dart - dart

I have a variable's declaration like this;
String user1="John"; String user2="Smith"; ....
is there any way to call the variables in for loop;
for(var i=1;i<3:i++) { print("${user[i]}"; }

You can use List and get values with any loop.
List<String> names = ['John', 'Smith', 'Bob'];
for (var element in names) {
print(element);
}
for (var element in names) {
print(element);
}
for (var i = 0; i< names.length; i++) {
print(names[i]);
}

Related

asp.net mvc: .net core: how to map stored proc result set to class fields

I got this simple model class:
public class PrvProduct
{
[Key]
public Int32 ProductId
{
get; set;
}
public Int64 ProductLineId;
public String MfgPartNumber;
public String ProductName;
public String ProductDescription;
}
I'm trying to call a stored proc, using .net core, it works fine, returns a list of PrvProduct objects. problem is: their fields are empty, unless I fill them up myself in code. ProductId is always there, not sure why (maybe because i typed there the [key] attribute?) but the rest are not.
is there a simple way to map class fields to results sets, like in ado.net (i would just do SQLDataAdapter.Fill(MyDataTable) and the MyDataTable fields will have the values by field name)... or do i have to do option 2 below every time?
Many thanks!
string sqlQuery = "EXEC Maint.GetProductList '" + sNameFilter + "'";
//option 1: this gets no value in the fields of each PrvProduct (ProductId gets value maybe because its [key], the others don't)
IQueryable results = _context.Products.FromSql(sqlQuery).AsNoTracking();
//option 2: this works, but... do i have to do this for every stored proc i call, every field, or is there a beter way to map class fields to returned results fields?
List<PrvProduct> oList = new List<PrvProduct>();
using (var command = _context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = sqlQuery;
command.CommandType = CommandType.Text;
_context.Database.OpenConnection();
using (var result = command.ExecuteReader())
{
while (result.Read())
{
// Map to your entity
oList.Add(new PrvProduct
{
ProductId = result.GetInt32(0),
ProductName = result.GetString(1)
});
}
}
}
In EF Core, if you execute a stored procedure using one of your DbSet entities then it will map it automatically. The problem is that in many case you need to map a stored procedure to a DTO, for example, and the DTO is not part of your DbSet entities. In those cases you need to go back in time and map it manually which is a waste of time.
In order to avoid mapping the data reader manually, I added a bunch of extension methods that do it for you. The code is not perfect and I'm still improving it but it's good enough in most of the cases.
Once you add the extensions methods I'm gonna describe below, you can use it like this:
return dbContext.Database.SqlQuery<SalesReportDTO>("spGetSalesReport",
SqlParameterBuilder.Build("customerId", customerId),
SqlParameterBuilder.Build("dateFrom", from),
SqlParameterBuilder.Build("dateTo", to)).ToList();
DatabaseFacadeExtensions: adds extensions methods to DatabaseFacade class, allowing you to call the method SqlQuery from dbContext.Database just like we used to do with Entity Framework 6.
public static class DatabaseFacadeExtensions
{
public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, params SqlParameter[] parameters)
{
return SqlQuery<T>(database, query, null, CommandType.StoredProcedure, parameters);
}
public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, CommandType commandType, params SqlParameter[] parameters)
{
return SqlQuery<T>(database, query, null, commandType, parameters);
}
public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, int? commandTimeout, params SqlParameter[] parameters)
{
return SqlQuery<T>(database, query, commandTimeout, CommandType.StoredProcedure, parameters);
}
public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, int? commandTimeout, CommandType commandType, params SqlParameter[] parameters)
{
using (var cmd = database.GetDbConnection().CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = commandType;
if (commandTimeout.HasValue)
{
cmd.CommandTimeout = commandTimeout.Value;
}
cmd.Parameters.AddRange(parameters);
if (cmd.Connection.State == System.Data.ConnectionState.Closed)
{
cmd.Connection.Open();
}
try
{
using (var reader = cmd.ExecuteReader())
{
return reader.MapToList<T>();
}
}
finally
{
cmd.Connection.Close();
}
}
}
}
DbDataReaderExtensions: adds extensions methods to DbDataReader class so it can map the data reader to your own clases.
public static class DbDataReaderExtensions
{
public static List<T> MapToList<T>(this DbDataReader dr)
{
var objList = new List<T>();
if (dr.HasRows)
{
bool isSingleValue = typeof(T).IsPrimitive || typeof(T) == typeof(string);
IEnumerable<PropertyInfo> props = null;
Dictionary<string, DbColumn> colMapping = null;
if (!isSingleValue)
{
props = typeof(T).GetRuntimeProperties();
colMapping = dr.GetColumnSchema()
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
.ToDictionary(key => key.ColumnName.ToLower());
}
while (dr.Read())
{
T obj;
if (isSingleValue)
{
obj = (T)dr.GetValue(0);
}
else
{
obj = Activator.CreateInstance<T>();
foreach (var prop in props)
{
string propertyName = prop.Name.ToLower();
if (!colMapping.ContainsKey(propertyName))
{
continue;
}
var val = dr.GetValue(colMapping[propertyName].ColumnOrdinal.Value);
if (val != DBNull.Value)
{
// enum property
if (prop.PropertyType.IsEnum)
{
prop.SetValue(obj, Enum.ToObject(prop.PropertyType, val));
}
// nullable enum property
if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) && Nullable.GetUnderlyingType(prop.PropertyType).IsEnum)
{
prop.SetValue(obj, Enum.ToObject(Nullable.GetUnderlyingType(prop.PropertyType), val));
}
else
{
prop.SetValue(obj, val);
}
}
}
}
objList.Add(obj);
}
}
return objList;
}
public static T MapToObject<T>(this DbDataReader dr)
{
var props = typeof(T).GetRuntimeProperties();
if (dr.HasRows)
{
var colMapping = dr.GetColumnSchema()
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
.ToDictionary(key => key.ColumnName.ToLower());
if (dr.Read())
{
T obj = Activator.CreateInstance<T>();
foreach (var prop in props)
{
var val = dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
prop.SetValue(obj, val == DBNull.Value ? null : val);
}
return obj;
}
}
return default(T);
}
}
The next class is optional but I use to build parameters in a simpler way and it's needed in the example I described above:
public class SqlParameterBuilder
{
public static SqlParameter Build(string name, bool? value)
{
if (value.HasValue)
{
return new SqlParameter() { ParameterName = name, Value = value.Value };
}
return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
}
public static SqlParameter Build(string name, int? value)
{
if (value.HasValue)
{
return new SqlParameter() { ParameterName = name, Value = value.Value };
}
return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
}
public static SqlParameter Build(string name, string value)
{
if (value != null)
{
return new SqlParameter() { ParameterName = name, Value = value };
}
return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
}
public static SqlParameter Build(string name, DateTime? value)
{
if (value != null)
{
return new SqlParameter { ParameterName = name, SqlDbType = SqlDbType.DateTime, Value = value };
}
return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
}
public static SqlParameter Build(string name, Guid? value)
{
if (value.HasValue)
{
return new SqlParameter { ParameterName = name, SqlDbType = SqlDbType.UniqueIdentifier, Value = value };
}
return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
}
public static SqlParameter Build(string name, int[] values)
{
SqlParameter par = new SqlParameter(name, SqlDbType.Structured);
par.TypeName = "dbo.IntParameterList";
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
par.Value = dt;
if (values != null)
{
foreach (int value in values.Where(p => p != 0))
{
dt.Rows.Add(value);
}
}
return par;
}
public static SqlParameter Build(string name, string[] values, VarcharParameterListEnum varcharParameterListType = VarcharParameterListEnum.Varchar50)
{
SqlParameter par = new SqlParameter(name, SqlDbType.Structured);
switch(varcharParameterListType)
{
case VarcharParameterListEnum.Varchar15:
par.TypeName = "dbo.Varchar15ParameterList";
break;
case VarcharParameterListEnum.Varchar50:
par.TypeName = "dbo.Varchar50ParameterList";
break;
case VarcharParameterListEnum.Varchar100:
par.TypeName = "dbo.Varchar100ParameterList";
break;
case VarcharParameterListEnum.Varchar255:
par.TypeName = "dbo.Varchar255ParameterList";
break;
case VarcharParameterListEnum.Varchar510:
par.TypeName = "dbo.Varchar510ParameterList";
break;
}
DataTable dt = new DataTable();
dt.Columns.Add("textValue", typeof(string));
par.Value = dt;
if (values != null)
{
foreach (var value in values.Where(p => !string.IsNullOrWhiteSpace(p)))
{
dt.Rows.Add(value);
}
}
return par;
}
}

dart polymer - Breaking on exception: Concurrent modification during iteration: Instance of 'ObservableList'

I have an error: "ConcurrentModificationError" - Breaking on exception: Concurrent modification during iteration: Instance of 'ObservableList'.
When I want delete some items by ObservableList during "ForEach" used to "search" items.
Code Example:
.html
<template repeat="{{f in SelectedFiles}}">
<li>
<span class="label">{{f.name}}"">
<button class="tiny" on-click="{{deleteDataSetFile}}" data-file="{{f.path}}">Delete</button>
</li>
</template>
.dart
#observable List<String> fileSelected;
void deleteDataSetFile(Event event, var detail, var target) {
String datafile = target.attributes['data-file'];
for(var file in this.SelectedFiles){
if(file.path==datafile){
this.SelectedFiles.remove(file);
}
}
}
This doesn't work in most programming languages.
Workarounds:
iterate over a copy of the list
#observable List<String> fileSelected;
void deleteDataSetFile(Event event, var detail, var target) {
String datafile = target.attributes['data-file'];
for(var file in this.SelectedFiles.toList()){ // added .toList() which returns a copy
if(file.path==datafile){
this.SelectedFiles.remove(file);
}
}
}
store the elements and remove them later
#observable List<String> fileSelected;
void deleteDataSetFile(Event event, var detail, var target) {
String datafile = target.attributes['data-file'];
List<String> itemsToRemove = [];
for(var file in this.SelectedFiles){
if(file.path==datafile){
itemsToRemove.add(file);
}
}
for(var file in itemsToRemove) {
this.SelectedFiles.remove(file);
}
}
if you iterate differently you can delete while iterating
for(int i = 0; i < this.SelectedFiles.length;){
if(file.path==datafile){
this.SelectedFiles.removeAt(i)
} else {
i++;
}
}
or use the retainWhere/removeWhere method of List
this.SelectedFiles.retainWhere((e) => e.path != dataFile);
this.SelectedFiles.removeWhere((e) => e.path == dataFile);
SOLUTION in ".dart"
#observable List<String> fileSelected;
void deleteDataSetFile(Event event, var detail, var target) {
String datafile = target.attributes['data-file'];
var tmp;
for(var file in this.SelectedFiles){
if(file.path==datafile){
tmp = file;
}
}
if(tmp!=null){
this.SelectedFiles.remove(tmp);
}
}

passing a list to javascript in mvc

I have a list of image urls that I am trying to display. I am passing the list from the controller to the view. I know that the list is being created successfully. But when it gets to the view, javascript interprets it as "*System.Collections.Generic.List1[System.String]*`" not as the actual list. This causes the images not to be displayed.
Here is the line of code that I am using to assign the list to js variable:
var imageUrls = '#Model.PicUrls';
and the controller
public ActionResult Index()
{
var pics = _ctx.Image.Select(m => m).Take(10).ToList<ImageModel>();
var picUrls = new List<string>();
for (int i = 0; i <= pics.Count - 1; i++)
{
picUrls.Add(pics[i].ImageUrl);
}
var outModel = new ViewPostViewModel
{
PicUrls = picUrls
};
return View(outModel);
I tried to return a Json object but then the page literally only displayed was the completed list.
return Json(outModel.PicUrls, JsonRequestBehavior.AllowGet);
So, the Json advice worked somewhat but it is not quite there
try it
public ActionResult Index()
{
var pics = _ctx.Image.Select(m => m.ImageUrl)
.Take(10).ToList();
var picUrls = new List();
for (int i = 0; i <= pics.Count - 1; i++)
{
picUrls.Add(pics[i]);
}
var outModel = new ViewPostViewModel
{
PicUrls = picUrls
};
return Json(outModel.PicUrls, JsonRequestBehavior.AllowGet);
}
Getting
System.Collections.Generic.List`1[System.String]
because you're model value PicUrls default ToString() implementation is to return its type.
You could store PicUrls as a JSON string, then parse to javascript array in your js.
public ActionResult Index()
{
var pics = _ctx.Image.Select(m => m).Take(10).ToList();
var picUrls = String.Empty;
for (int i = 0; i <= pics.Count - 1; i++)
{
picUrls += (picUrls != String.Empty ? ", " : "") + #"""" + pics[i].ImageUrl + #"""";
}
var outModel = new ViewPostViewModel
{
PicUrls = #"[" + picUrls + "]";
};
return View(outModel);
In your js, use
var imageUrls = JSON.parse('#Model.PicUrls');

Using dynamic objects with ASP.NET MVC model binding

In an ASP.NET MVC3 application, if I wanted to model bind my form post data to an ExpandoObject (or my own object derived from DynamicObject where I implement my own Try... members) would I need to write my own custom model binder?
If I do:
public ActionResult Save(ExpandoObject form)
{
....
}
The value of form is null.
Or if I have:
public class MyDynamicThing : DynamicObject
{
public int Id { get; set; }
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Set breakpoint here but doesn't get hit when model binding
return base.TrySetMember(binder, value);
}
}
...and in my controller:
public ActionResult Save(MyDynamicThing form)
{
....
}
In the above example Id is set to the value from the form. However if I set a breakpoint in TrySetMember this doesn't get hit.
Are there any magical incantations I can invoke to coerce the built-in model binder to work with ExpandoObjects or my own classes derived from DynamicObject?
I could resort to picking up the raw form post collection but I have to serialise this data to JSON which would mean an extra and untidy step to harvest those values.
No, this is not possible with the built-in model binder. You could of course write a custom model binder. The only property that the built-in model binder is capable of binding is the one that it seems from the MyDynamicThing type and that's why it can only set the Id property. It has no knowledge of other properties.
Try this:
public class ExpandoObjectBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException("bindingContext");
IDictionary<string, object> model = new ExpandoObject();
string modelName = bindingContext.ModelName;
var form = controllerContext.HttpContext.Request.Unvalidated.Form;
var keys = form.AllKeys.Where(k => k.StartsWith(modelName + "."));
Debug.Write("ExpandoObjectBinder keys count is " + keys.Count());
foreach (var key in keys)
{
var propName = key.Replace(model + ".", "");
model.Add(propName, form[key]);
}
if (model.Count == 0)
throw new Exception("Data is empty.");
return model;
}
}
Register the binder mvc initialization :
ModelBinders.Binders.Add(typeof(ExpandoObject), new ExpandoObjectBinder());
Type support added (int, byte, long, decimal, string, array and subobjects):
public class ExpandoObjectBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException("bindingContext");
string modelName = bindingContext.ModelName;
var form = controllerContext.HttpContext.Request.Unvalidated.Form;
var model = ParseProperties(modelName, form);
return model;
}
public object ParseProperties(string modelName, NameValueCollection form)
{
var keys = form.AllKeys.Where(k => k.StartsWith(modelName + "."));
Debug.WriteLine("ExpandoObjectBinder keys count is " + keys.Count() + " for " + modelName);
IDictionary<string, object> model = new ExpandoObject();
List<string> subModelNames = new List<string>();
List<string> arrModelNames = new List<string>();
//ModelName: Dialog.Attributes[0].Options
foreach (var key in keys)
{
//Dialog.Attributes[0].Options.Byte
//Dialog.Attributes[0].Options.Inner.Byte
//Dialog.Attributes[0].Options.Inner.Integer
//Dialog.Attributes[0].Options.SimpleArray[0]
//Dialog.Attributes[0].Options.SimpleArray[1]
var propName = key.Replace(modelName + ".", "");
//Byte
//Inner.Byte
//Inner.Integer
//SimpleArray[0]
//SimpleArray[1]
if (!(propName.Contains('[') || propName.Contains('.')))
{
model.Add(propName, GetValue(form, key));
}
//array (can allow sub objects)
if (propName.Contains('['))
{
var names = propName.Split('[');
var arrModelName = names[0];
if (!arrModelNames.Contains(arrModelName))
arrModelNames.Add(arrModelName);
}
//not array but can has sub objects
if (!propName.Contains('[') && propName.Contains('.'))
{
var names = propName.Split('.');
var subModelName = names[0];
if (!subModelNames.Contains(subModelName))
subModelNames.Add(subModelName);
}
}
foreach (var subModelName in subModelNames)
{
var key = modelName + "." + subModelName;
object val = form[key];
val = ParseProperties(key, form);
model.Add(subModelName, val);
}
foreach (var arrModelName in arrModelNames)
{
//Dialog.Attributes[0].Options.SimpleArray[
var key = modelName + "." + arrModelName + "[";
var arrKeys = form.AllKeys.Where(k => k.StartsWith(key));
var isComplexArray = false;
int length = 0;
foreach (var arrKey in arrKeys)
{
var aKey = arrKey.Replace(key, "");
if (aKey.Contains("."))
isComplexArray = true;
var parsed = aKey.Split(']');
var num = int.Parse(parsed[0]);
if (num > length)
length = num;
}
List<object> vals = new List<object>();
if (isComplexArray)
{
for (int i = 0; i < length + 1; i++)
{
var arrKey = key + i + "]";
object val = ParseProperties(arrKey, form);
vals.Add(val);
}
}
else
{
for (int i = 0; i < length + 1; i++)
{
var arrKey = key + i + "]";
vals.Add(GetValue(form, arrKey));
}
}
model.Add(arrModelName, vals);
}
return model;
}
object GetValue(NameValueCollection form, string key)
{
object val = form[key];
if (decimal.TryParse(form[key], out decimal decimalVal))
val = decimalVal;
if (long.TryParse(form[key], out long longVal))
val = longVal;
if (int.TryParse(form[key], out int intVal))
val = intVal;
if (byte.TryParse(form[key], out byte byteVal))
val = byteVal;
if (bool.TryParse(form[key], out bool boolVal))
val = boolVal;
return val;
}
}

How can a formcollection be enumerated in ASP.NET MVC?

How can I enumerate through all the key/values of
a FormCollection (system.web.mvc) in ASP.NET MVC?
Here are 3 ways to do it specifically with a FormCollection object.
public ActionResult SomeActionMethod(FormCollection formCollection)
{
foreach (var key in formCollection.AllKeys)
{
var value = formCollection[key];
}
foreach (var key in formCollection.Keys)
{
var value = formCollection[key.ToString()];
}
// Using the ValueProvider
var valueProvider = formCollection.ToValueProvider();
foreach (var key in valueProvider.Keys)
{
var value = valueProvider[key];
}
}
foreach(KeyValuePair<string, ValueProviderResult> kvp in form.ToValueProvider())
{
string htmlControlName = kvp.Key;
string htmlControlValue = kvp.Value.AttemptedValue;
}
foreach(var key in Request.Form.AllKeys)
{
var value = Request.Form[key];
}
In .NET Framework 4.0, the code to use the ValueProvider is:
IValueProvider valueProvider = formValues.ToValueProvider();
foreach (string key in formValues.Keys)
{
ValueProviderResult result = valueProvider.GetValue(key);
string value = result.AttemptedValue;
}
I use this:
string keyname;
string keyvalue;
for (int i = 0; i <= fc.Count - 1; i++)
{
keyname = fc.AllKeys[i];
keyvalue = fc[i];
}
hope it helps someone.
And in VB.Net:
Dim fv As KeyValuePair(Of String, ValueProviderResult)
For Each fv In formValues.ToValueProvider
Response.Write(fv.Key + ": " + fv.Value.AttemptedValue)
Next

Resources