I Have Excel import feature with ClosedXM and meet the errror with ctivator.CreateInstance(typeof(T)). It throws:
System.MissingMethodException: 'Cannot dynamically create an instance of type
'FSH.WebApi.Domain.Catalog.Brand'.
Reason: No parameterless constructor defined.
Please help !!!
// Controller
[HttpPost("import")]
public async Task<ActionResult<int>> ImportAsync(ImportBrandsRequest request)
{
IList<Brand> result = new List<Brand>();
result = await _excelReader.ImportAsync<Brand>(request.ExcelFile, FileType.Excel);
return Ok(result.Count);
}
// Interface
public interface IExcelReader : ITransientService
{
Task<IList<T>> ImportAsync<T>(
FileUploadRequest request,
FileType supportedFileType,
string sheetName = "Sheet1");
}
// Service:
public class ExcelReader : IExcelReader
{
public async Task<IList<T>> ImportAsync<T>(FileUploadRequest request, FileType supportedFileType, string sheetName = "Sheet1")
{
var streamData = new MemoryStream(Convert.FromBase64String(base64Data));
List<T> list = new List<T>();
Type typeOfObject = typeof(T);
using (IXLWorkbook workbook = new XLWorkbook(streamData))
{
var worksheet = workbook.Worksheets.First(w => w.Name == sheetName);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
// header column texts
var columns = worksheet.FirstRow().Cells().Select((v, i) => new { v.Value, Index = i + 1 });
// indexing in closedxml starts with 1 not from 0
// Skip first row which is used for column header texts
foreach (IXLRow row in worksheet.RowsUsed().Skip(1))
{
T item = (T)Activator.CreateInstance(typeof(T));
// T item = (T)Activator.CreateInstance(typeof(T));
foreach (PropertyDescriptor prop in properties)
{
int colIndex = columns.Single(
c => c.Value.ToString() == prop.Name).Index;
if (colIndex == 0) continue;
object? val = row.Cell(colIndex).Value;
var type = prop.PropertyType;
prop.SetValue(item, Convert.ChangeType(val, type));
}
if (item != null) list.Add(item);
}
}
return await Task.FromResult(list);
}
Presumably, Brand doesn't have a constructor without parameters. So, either add a parameterless constructor to Brand or pass parameter arguments to Activator.CreateInstance.
My datagrid in WPF app. displays csv file.I want to copy csv file to an array.Remove a string from array which is same as the selected row from datagrid (comparing indexes).In the end I display the string array in second datagrid.
//Storing csv file in string array
var filePath = "csvFile.csv";
using (StreamReader file = new StreamReader(filePath))
{
while (!file.EndOfStream)
{
int selectedIndex =int.Parse(dgData.SelectedIndex.ToString());
string strResult = file.ReadToEnd();
string[] result = strResult.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
List<string> list = new List<string>(result);
list.RemoveAt(selectedIndex);
foreach (string item in list)
{
Console.WriteLine(item);
Console.ReadLine();
}
dgtest.ItemsSource = list;
}
file.Close();
}
I would appreciate correcting my code.At the moment I have an error stating:
Index is out of range.
You are complicating things. Try something like this:
const string FilePath = "csvFile.csv";
List<string> lines = File.ReadAllLines(FilePath)?.ToList();
int selectedIndex = dgData.SelectedIndex;
if (lines != null && selectedIndex > 0 && lines.Count > selectedIndex)
lines.RemoveAt(selectedIndex);
dgtest.ItemsSource = lines;
I have field hobbies in table, which have; Reading,Sport,Paint
I want to checked back in gridview whichever hobbies's they have.
I insert in table used:
foreach (ListItem item in chkbxHobbies.Items)
{
if (item.Selected)
{
objBAL.HOBBIES += item + ",";
}
}
where chkGVHobbies is CheckBoxList control inside gridview.
i hope you already retrive particuler record in DataTable
CheckBoxList chkhbs = (CheckBoxList)GridView1.Rows[e.NewEditIndex].FindControl("chkGVHobbies");
string hbs = Convert.ToString(dt.Rows[0]["hobbies"]);
string[] str = hbs.Split(',');
foreach (string item in str)
{
foreach (ListItem gvchk in chkhbs.Items)
{
if (gvchk.Text==item)
{
gvchk.Selected = true;
}
}
I have functions that is being called within a WCF service function and I get the exception stated above at the subcategoriesGenerator function on the excute reader line
isn't it supposed for the cmd created in the second function to a completely different instance than the other one
please I'm confused and I need help ant suggestions?
public static List<Category> categoryGenerator(ref SqlConnection con)
{
Category category = null;
List<Category> list = null;
List<SubCategory> subcategoryList = null;
string categoryName = null;
string categoryLink = null;
SqlCommand cmd = new SqlCommand("sp_categoriesgenerator", con);
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while(reader.Read())
{
categoryName = reader["CategoryName"].ToString();
categoryLink = reader["CategorySEO"].ToString() + "/";
subcategoryList = subcategoriesGenerator(ref con, Convert.ToInt32(reader["CategoryId"].ToString()));
category.categoryName = categoryName;
category.categoryLink = categoryLink;
category.subcategories = subcategoryList;
list.Add(category);
category = null;
}
reader.Close();
return list;
}//end CategoryGenerator
public static List<SubCategory> subcategoriesGenerator(ref SqlConnection con, int categoryId)
{
SubCategory subcategory = null;
List<SubCategory> list = null;
string SubCategoryName = null;
string SubCategoryLink = null;
SqlCommand cmd = new SqlCommand("sp_subcategoriesgenerator", con);
cmd.Parameters.AddWithValue("#categoryID", categoryId);
SqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
SubCategoryName = reader["SubcategoryName"].ToString();
SubCategoryLink = reader["CategorySEO"].ToString() + "/" + reader["SubcategorySEO"] + "/";
subcategory.subcategoryName = SubCategoryName;
subcategory.subcategoryLink = SubCategoryLink;
list.Add(subcategory);
subcategory = null;
}
reader.Close();
return list;
}// end subcategoriesGenerator
You can't open another reader in your connection while you have an open reader. You have to extract the call of the function "subcategoriesGenerator" outside of your first while-statement or create a second database-connection. I prefer this solution:
First, collect all categories
Second, loop over all categories and query the subcategories and append them to your category-object
var questions:Array = new Array;
questions[0] = "qname:mc_01, qvalue:1";
questions[1] = "qname:mc_02, qvalue:1";
questions[2] = "qname:mc_03, qvalue:1";
questions[3] = "qname:mc_04, qvalue:1";
questions[4] = "qname:mc_05, qvalue:1";
questions[5] = "qname:mc_06, qvalue:1";
questions[6] = "qname:mc_07, qvalue:1";
questions[7] = "qname:mc_08, qvalue:1";
questions[8] = "qname:mc_09, qvalue:1";
questions[9] = "qname:mc_10, qvalue:1";
questions[10] = "qname:mc_11, qvalue:2";
questions[11] = "qname:mc_12, qvalue:2";
questions[12] = "qname:mc_13, qvalue:2";
questions[13] = "qname:mc_14, qvalue:2";
questions[14] = "qname:mc_15, qvalue:2";
questions[15] = "qname:mc_16, qvalue:2";
questions[16] = "qname:mc_17, qvalue:2";
questions[17] = "qname:mc_18, qvalue:2";
questions[18] = "qname:mc_19, qvalue:2";
questions[19] = "qname:mc_20, qvalue:2";
questions[20] = "qname:mc_21, qvalue:3";
questions[21] = "qname:mc_22, qvalue:3";
questions[22] = "qname:mc_23, qvalue:3";
questions[23] = "qname:mc_24, qvalue:3";
questions[24] = "qname:mc_25, qvalue:3";
questions[25] = "qname:mc_26, qvalue:3";
questions[26] = "qname:mc_27, qvalue:3";
questions[27] = "qname:mc_28, qvalue:3";
questions[28] = "qname:mc_29, qvalue:3";
questions[29] = "qname:mc_30, qvalue:3";
I've got this array and want to access the qname property and can't remember how to do it. Is it something like questions[0].qname or questions[0](qname)?
You've defined your array elements as string instead of objects.
Try this instead:
var questions:Array = new Array;
questions[0] = {qname:mc_01, qvalue:1};
...
Curly braces instead of double-quotation marks. With quotation marks you create strings. With curly braces, you can create dynamic objects and set their properties. So if you are creating a string value for qname, make sure you define it as qname:"mc_01" instead of qname:mc_01.
So you can use questions[0].qname or questions[0]["qname"] to access the properties.
But if you can't do that what is told in previous answer (e.g. you get those strings from server) you can use regular expresions to get those values nicely:
var searchPattern : RegExp = /(?P<qname>(?<=qname\:)[a-zA-Z0-9_]+(?=[\s,]*))/g;
trace( searchPattern.exec(questions[1]).qname ); // traces out: mc_02
As you tagged ActionScript 3.0, and its a strongly typed language, I would recommend a typed class to hold your data structure.
package your.package.name
{
public class Question
{
protected var _name:String;
protected var _value:String;
public function Question(name:String = null, value:String = null)
{
this.name = name;
this.value = value;
}
public function get name():String
{
return _name;
}
public function set name(value:String):void
{
_name = value;
}
public function get value():String
{
return _value;
}
public function set value(value:String):void
{
_value = value;
}
}
}
By having getters and setters and also exposing these props in the constructor you can create them in two ways:
var question:Question = new Question("Question1", "Question value");
OR:
var question:Question = new Question();
question.name = "Question1";
question.value = "Question value";
This offers benefits in terms of intellisense for getting properties in your ide and also type safety to stop you putting in incorrect types for name and value.
Then to get hold of a question:
questions[0].name; // in this example Question1
questions[0].value; // in this example Question value
Usually your questions would be coming from some data source, like xml or a web service, whatever I'll use literal xml for this example, in that scenario you would want to build your objects in some loop eg:
var questionsXML:XML =
<questions>
<question name="Question1">Question1 value</question>
<question name="Question2">Question2 value</question>
<question name="Question3">Question3 value</question>
</questions>
Then:
var questions:Array = [];
for each (var questionXML:XML in questionsXML.question)
{
var question:Question = new Question();
question.name = questionXML.#name;
question.value = questionXML.text();
questions.push(question);
}