breezejs: overriding displayname - breeze

I'm in the process of customizing validation messages. It's working fine using the messageTemplates property. However it uses %displayName% to render the name of the property and I can't find out how to override this value ? Is there anyway to do that ?

I was wanting to do this also but I wanted to use the [DisplayName] attribute from my EF model. I couldn't find anyone that had an example of doing this so after I found a way I thought I would share.
First, I extended the metadata returned from my BreezeController:
[HttpGet]
public string Metadata()
{
// Extend metadata with extra attributes
JObject metadata = JObject.Parse(contextProvider.Metadata());
string nameSpace = metadata["schema"]["namespace"].ToString();
foreach (var entityType in metadata["schema"]["entityType"])
{
string typeName = entityType["name"].ToString();
Type t = Type.GetType(nameSpace + "." + typeName);
foreach (var prop in t.GetProperties())
{
foreach (var attr in prop.CustomAttributes)
{
string name = attr.GetType().Name;
foreach (var p in entityType["property"])
{
if (prop.Name == p["name"].ToString()) {
if (attr.AttributeType.Name == "DisplayNameAttribute") {
DisplayNameAttribute a = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
p["displayName"] = a.DisplayName;
break;
}
}
}
}
}
}
return metadata.ToString();
}
Then I added a little javascript after the metadata load to poke the display names from the augmented metadata where Breeze wants to find them.
manager.fetchMetadata().then(function (md) {
angular.forEach(md.schema.entityType, function (et) {
var etype = manager.metadataStore.getEntityType(et.name);
angular.forEach(et.property, function (p) {
var prop = etype.getProperty(p.name);
prop.displayName = p.displayName;
});
});
console.log("starting app");
angular.bootstrap($("#app"), ["app"]);
});
I'm using angular so if you aren't you can ignore the angular stuff and probably get the idea. This seems to work rather nicely. It should be pretty easy to extend this to other model attributes as well like the RegularExpression validation attribute. I'll probably work on that next.
FYI, some of this code is not optimized and could probably be refactored, prettied up a bit but I just got it working and thought I would share. If anyone has any suggestions of a better way let me know. Hopefully Breeze will allow extending the metadata in a more supported way in the future. This does seem like a bit of a hack.

This is not YET well documented but you can simply set the 'displayName' property on any dataProperty and this will override the autogenerated display name and will be used for all validation messages for this property. So
var custType = myEntityManager.metadataStore.getEntityType("Customer");
var dp = custType.getProperty("companyName");
dp.displayName = "My custom display name";
Also, please see "Customize the message templates" at the bottom of this page: Breeze Validation

Following jpcoder request for suggestions, here goes my slightly improved server portion:
JObject metadata = JObject.Parse(contextProvider.Metadata());
string nameSpace = metadata["schema"]["namespace"].ToString();
foreach (var entityType in metadata["schema"]["entityType"])
{
string typeName = entityType["name"].ToString();
Type t = Type.GetType(nameSpace + "." + typeName);
IEnumerable<JToken> metaProps = null;
if (entityType["property"].Type == JTokenType.Object)
metaProps = new[] { entityType["property"] };
else
metaProps = entityType["property"].AsEnumerable();
var props = from p in metaProps
let pname = p["name"].ToString()
let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
where prop != null
from attr in prop.CustomAttributes
where attr.AttributeType.Name == "DisplayNameAttribute"
select new
{
Prop = p,
DisplayName = ((DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute))).DisplayName
};
foreach (var p in props)
p.Prop["displayName"] = p.DisplayName;
}

Looking at http://www.breezejs.com/sites/all/apidocs/files/a40_entityMetadata.js.html#l1452,
could this be improved by renaming the existing "name" value to nameOnServer (to satisfy the getDataProperty call) and inserting the DisplayNameAttribute value as "name"?

A necessary change to the server code is that, if your model classes are in different assemblies, you cannot use
Type t = Type.GetType(nameSpace + "." + typeName);
You need the namespace per type (which is in the metadata), and (I think) to use BuildManager to locate the appropriate types in different assemblies. The mapping from cSpaceOSpaceMapping might be achieved more elegantly, but I didn't have time to research the different json formatting options.
JObject metadata = JObject.Parse(UnitOfWork.Metadata());
string EFNameSpace = metadata["schema"]["namespace"].ToString();
string typeNameSpaces = metadata["schema"]["cSpaceOSpaceMapping"].ToString();
typeNameSpaces = "{" + typeNameSpaces.Replace("],[", "]|[").Replace("[", "").Replace("]", "").Replace(",", ":").Replace("|", ",") + "}";
JObject jTypeNameSpaces = JObject.Parse(typeNameSpaces);
foreach (var entityType in metadata["schema"]["entityType"])
{
string typeName = entityType["name"].ToString();
string defaultTypeNameSpace = EFNameSpace + "." + typeName;
string entityTypeNameSpace = jTypeNameSpaces[defaultTypeNameSpace].ToString();
Type t = BuildManager.GetType(entityTypeNameSpace, false);
IEnumerable<JToken> metaProps = null;
if (entityType["property"].Type == JTokenType.Object)
metaProps = new[] { entityType["property"] };
else
metaProps = entityType["property"].AsEnumerable();
var props = from p in metaProps
let pname = p["name"].ToString()
let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
where prop != null
from attr in prop.CustomAttributes
where attr.AttributeType.Name == "DisplayNameAttribute"
select new
{
Prop = p,
DisplayName = ((DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute))).DisplayName
};
foreach (var p in props)
{
p.Prop["displayName"] = p.DisplayName;
}
}

JObject metadata = JObject.Parse(this._context.Metadata());
string EFNameSpace = metadata["schema"]["namespace"].ToString();
string typeNameSpaces = metadata["schema"]["cSpaceOSpaceMapping"].ToString();
typeNameSpaces = "{" + typeNameSpaces.Replace("],[", "]|[").Replace("[", "").Replace("]", "").Replace(",", ":").Replace("|", ",") + "}";
JObject jTypeNameSpaces = JObject.Parse(typeNameSpaces);
foreach (var entityType in metadata["schema"]["entityType"])
{
string typeName = entityType["name"].ToString();
string defaultTypeNameSpace = EFNameSpace + "." + typeName;
string entityTypeNameSpace = jTypeNameSpaces[defaultTypeNameSpace].ToString();
Type t = BuildManager.GetType(entityTypeNameSpace, false);
IEnumerable<JToken> metaProps = null;
if (entityType["property"].Type == JTokenType.Object)
metaProps = new[] { entityType["property"] };
else
metaProps = entityType["property"].AsEnumerable();
var props = from p in metaProps
let pname = p["name"].ToString()
let prop = t.GetProperties().SingleOrDefault(prop => prop.Name == pname)
where prop != null
from attr in prop.CustomAttributes
where attr.AttributeType.Name == "DisplayAttribute"
select new
{
Prop = p,
DisplayName = ((DisplayAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayAttribute))).Name
};
foreach (var p in props)
{
p.Prop["displayName"] = p.DisplayName;
}
}
return metadata.ToString();

Improving jpcoder's answer ...
For me most of my DisplayName changes were to replace "PascalCaseFieldName" or "camelCaseFieldName" with "Upper Case Field Name". So rather than set every property DisplayName on the server, I applied a default function to set displayName.
End result was much less EF annotation required. My TypeScript is:
manager.metadataStore.getEntityTypes().forEach(function (storeEntityType) {
if (!(storeEntityType instanceof breeze.EntityType)) {
throw new Error("loadExtendedMetadata found '" + storeEntityType
+ "' StructuralType that is not an EntityType (e.g. a ComplexType)");
}
var extEntityType = extendedMetadata.entitiesExtended.find((extendedEntityType) => {
return extendedEntityType.shortName + ":#" + extendedEntityType.nameSpace === storeEntityType.name;
});
(storeEntityType as breeze.EntityType).getProperties().forEach((storeProperty) => {
//Both NavigationProperty & DataProperty have displayName & nameOnServer properties
var storeDataProperty = <breeze.DataProperty>storeProperty;
var extProperty;
if (extEntityType) {
extProperty = extEntityType.propertiesExtented.find((extendedProperty) => {
return extendedProperty.name === storeDataProperty.nameOnServer;
});
}
//Smart default: nameOnServer "PascalCaseFieldName" or "camelCaseFieldName" converted to "Upper Case Field Name"
storeDataProperty.displayName = (extProperty && extProperty.displayName)
|| storeDataProperty.nameOnServer.replace(/^./, function (str) {
// first ensure the first character is uppercase
return str.toUpperCase();
// insert a space before all caps, remove first character (added space)
}).replace(/([A-Z])/g, " $1").substring(1);
});
});

Related

am working on updating a single attribute in the User Model which is the balance attribute,

how I can update a single value for an already existing row in the db by only having a parameters that I want to add it to this attribute
here is my code for a trivial way but didnt work
public bool BuyBook(int BookId, int UserId, int BookPrice){
using (var ctx = new OnlineBooksEntities())
{
User updatedCustomer = (from c in ctx.Users
where c.UserId == UserId
select c).FirstOrDefault();
updatedCustomer.Balance = BookPrice;
ctx.SaveChanges();
}
this.DeleteBook(BookId);
return true;
}
Add an sql query to the method solves the update aim
public bool BuyBook(int BookId, int UserId, int BookPrice)
{
try
{
using (var ctx = new OnlineBooksEntities())
{
User user = ctx.Users.Where(x => x.UserId == UserId).FirstOrDefault();
BookPrice = (int)user.Balance + BookPrice;
int noOfRowUpdated =
ctx.Database.ExecuteSqlCommand("Update Users set Balance = "+BookPrice+ " where UserId ="+UserId);
}
Updating basically means changing an existing row's value. Since you mentioned EF, you can do this by retrieving the object, changing its value, and saving it back. Thus you can do something like this:
using (var db = new MyContextDB())
{
var result = db.Books.SingleOrDefault(b => b.BookPrice == bookPrice);
if (result != null)
{
result.SomeValue = "Your new value here";
db.SaveChanges();
}
}

Xamarin Android, get contact mobile number by using CursorLoader with selection and selection args

I'm trying to get contact details of a contact that the user picks from the contacts list in Android using Intent as the following code:
Intent Intent = new Intent(Intent.ActionPick, ContactsContract.Contacts.ContentUri);
Intent.SetType(ContactsContract.Contacts.ContentType);
StartActivityForResult(Intent, 3);
Now on the Intent results I run the following code to get specific contact information:
public override void OnActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == 3 && resultCode == -1 && data != null) //result code -1 means OK 0 Means cancelled Result.Ok
{
var ContactData = data.Data;
string ID = "";
string name = "";
string address = "";
byte[] picture = new byte[0];
List<string> numbers = new List<string>();
List<string> emails = new List<string>();
string mobile = "";
string email = "";
string selectionString = "id = ?";
string[] columnsNames = new string[] {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName,
ContactsContract.Contacts.InterfaceConsts.PhotoUri
};
var loader = new CursorLoader(Statics.mainActivity, ContactData, null, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
//Store Contact ID
string[] selectionStringArgs = new string[] { ID };
//Phone Numbers
string[] columnsNames2 = new string[] {
ContactsContract.CommonDataKinds.Phone.Number
};
var loader2 = new CursorLoader(Statics.mainActivity, ContactsContract.CommonDataKinds.Phone.ContentUri, columnsNames2, selectionString, selectionStringArgs, null);
var cursor2 = (ICursor)loader2.LoadInBackground();
while (cursor2.MoveToNext())
{
numbers.Add(cursor2.GetString(cursor2.GetColumnIndex(columnsNames2[0])));
}
//Email Address
string[] columnsNames3 = new string[] {
ContactsContract.CommonDataKinds.Email.Address
};
var loader3 = new CursorLoader(Statics.mainActivity, ContactsContract.CommonDataKinds.Email.ContentUri, columnsNames3, selectionString, selectionStringArgs, null);
var cursor3 = (ICursor)loader3.LoadInBackground();
while (cursor3.MoveToNext())
{
emails.Add(cursor3.GetString(cursor3.GetColumnIndex(columnsNames3[0])));
}
int TempRecepitntID = 0;
EmployeesViewModel tempRecipent = new EmployeesViewModel();
TempRecepitntID = Statics.mainActivity.currentViewModel.SelectedChat.ReceiverEmployee;
foreach (EmployeesViewModel evm in Statics.mainActivity.currentViewModel.Employees)
{
if (evm.ID == TempRecepitntID)
tempRecipent = evm;
}
new Android.Support.V7.App.AlertDialog.Builder(Statics.mainActivity)
.SetPositiveButton("Yes", (sender1, args) =>
{
Statics.mainActivity.currentViewModel.AddMessage(picture, tempRecipent, Statics.mainActivity.currentViewModel.SelectedChat.ID, "contact", 0, "", name, numbers[0], mobile, email, address);
})
.SetNegativeButton("No", (sender1, args) =>
{
// cancel
})
.SetMessage("Are you shure you want to send?")
.SetTitle("System Message")
.Show();
}
}
The problem is I want to retrieve only the information of the contact that the user selected but what I get is all other contacts data is retrieved so I tried to use the selection and selectionargs parameters of CursorLoader by setting string selectionString = "id = ?"; and selectionArgs to string[] selectionStringArgs = new string[] { ID }; the ID value is retrieved from the following code :
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
//Store Contact ID
string[] selectionStringArgs = new string[] { ID };
//Phone Numbers
string[] columnsNames2 = new string[] {
ContactsContract.CommonDataKinds.Phone.Number
};
But now it returns 0 results, I couldn't find anything on the internet that applies to Xamarin android, Please help.
Thanks,
Finally I found the solution, I used the following string in the selection parameter of the cursorloader method:
string selectionString = ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + ID;
and now only the selected contact numbers are retrieved.
I hope this will help someone else.
In additional information of #TMSL, I add the code afer this bloque
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
Here
selectionString = ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + ID;
Then I changed the parameters used in the definition of variable Loader2, converting selectionStringArgs in null.
var loader2 = new CursorLoader(this.Activity, ContactsContract.CommonDataKinds.Phone.ContentUri, columnsNames2, selectionString, null,null);
var cursor2 = (ICursor)loader2.LoadInBackground();
I found this documentation from xamarin guides
Uri – The fully qualified name of the ContentProvider.
Projection – Specification of which columns to select for the cursor.
Selection – Similar to a SQL WHERE clause.
SelectionArgs – Parameters to be substituted in the Selection.
SortOrder – Columns to sort by.
So, the variable selectionStringArgs used in the code from #TMSAL cannot use a value like "contact_id = 2700", because the parameter of CursorLoader SelectionArgs is not a filter but not "Parameters to be substituted in the Selection"
I hope this will help someone else too.

Given a TFS build definition how to get the value and type of an arbitrary process parameter?

Given a build definition, I extract the following pieces from it:
m_template = (DynamicActivity)WorkflowHelpers.DeserializeWorkflow(buildDefinition.Process.Parameters);
Properties = m_template.Properties.ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
Metadata = WorkflowHelpers.GetCombinedMetadata(m_template).ToDictionary(m => m.ParameterName);
m_parameters = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters)
Now I wish to know the value of an arbitrary process parameter.
My current code is:
public ParameterValue GetParameterValue(string name)
{
object propValue;
var valueType = GetParameterType(name, out propValue);
object value;
if (!m_parameters.TryGetValue(name, out value))
{
value = propValue;
}
return new ParameterValue(valueType, value);
}
private Type GetParameterType(string name, out object value)
{
value = null;
if (Properties != null)
{
DynamicActivityProperty property;
if (Properties.TryGetValue(name, out property))
{
var inArgument = property.Value as InArgument;
if (inArgument != null)
{
if (inArgument.Expression != null)
{
var exprString = inArgument.Expression.ToString();
if (!exprString.StartsWith(": VisualBasicValue<"))
{
value = exprString;
}
}
return inArgument.ArgumentType;
}
if (property.Value != null)
{
value = property.Value;
return property.Value.GetType();
}
var typeName = property.Type.ToString();
if (typeName.StartsWith(IN_ARGUMENT_TYPE_NAME_PREFIX))
{
typeName = typeName.Substring(IN_ARGUMENT_TYPE_NAME_PREFIX.Length, typeName.Length - IN_ARGUMENT_TYPE_NAME_PREFIX.Length - 1);
return Type.GetType(typeName, true);
}
return property.Type;
}
}
return typeof(string);
}
Unfortunately, this code stumbles for parameters satisfying all of the following conditions:
The parameter value is wrapped as InArgument<T>.
T is a non primitive type, for example string[]
The build definition does not override the value inherited from the process template.
What happens is that:
Because the value is non primitive exprString.StartsWith(": VisualBasicValue<") and I do not know how to handle it. Hence propValue is null.
Because the value is not overridden by the build definition !m_parameters.TryGetValue(name, out value) and hence I just return propValue.
As a result my logic returns null. But it is wrong! For example, I have a string[] parameter which has a list of string in the process template, but my logic returns null for the reasons explained.
So, what is the proper way to compute it?
You can use the following code (included in another link) to get value and type of one process parameter:
TfsTeamProjectCollection tfctc = new TfsTeamProjectCollection(new Uri("http://tfsservername:8080/tfs/DefaultCollection"));
IBuildServer bs = tfctc.GetService<IBuildServer>();
IBuildDetail[] builds = bs.QueryBuilds("teamprojectname", "builddefinitionname");
foreach (var build in builds)
{
var buildefinition = build.BuildDefinition;
IDictionary<String, Object> paramValues = WorkflowHelpers.DeserializeProcessParameters(buildefinition.ProcessParameters);
string processParametersValue = paramValues["argument1"].ToString();
Console.WriteLine(processParametersValue);
}
Also have a check on this case: TFS 2010: Why is it not possible to deserialize a Dictionary<string, object> with XamlWriter.Save when I can use XamlReader for deserializing

How to remove partucular list of querystring from current page url querystring in c#2.0

Say my current page url has got (http://mysite/english/faq.aspx?faqid=12123&cid=4545&intcid=65456&h=man)
string excludeQuerystring = DynConfig.Item("GoogleSEOLinkSettings/ExcludeQuerystring"); //this is the list of my exclude querystring (cid,intcid,del)
querystring = HttpContext.Current.Request.Url.AbsoluteUri.Split('?')[1]; //I will get faqid=12123&cid=4545,intcid=65456
StringBuilder fullQueryString = new StringBuilder();
if (!string.IsNullOrEmpty(excludeQuerystring) && !string.IsNullOrEmpty(querystring))
{
string[] strEQ = excludeQuerystring.Split(','); //making a array of excluded querystrings
NameValueCollection navValues = HttpUtility.ParseQueryString(querystring); //getting the list of querystring in NameValueCollection
if (navValues.Count > 0)
{
string[] strQ = navValues.AllKeys;
if(strQ.Length>0)
{
}
}
}
querystring= ?+faqid=12123&h=man //here I want updated querystring which does not have any querystring which is there in my excludeQuerystring
I am confused how to get this, actually I want to make a function which will do this all.
Please suggest!!
EDIT:
I applied new code to resolve above problem, however got little stuck while converting NameValueCollection to querystring again.
protected void Page_Load(object sender, EventArgs e)
{
string querystring = string.Empty;
string excludeList = "cid,intcid,del";
if (!string.IsNullOrEmpty(excludeList))
{
string getFinalString = GetQueryString(excludeList);
getFinalString = "?" + getFinalString;
}
}
public string GetQueryString(string excludeArray)
{
string retQueryString = string.Empty;
if (excludeArray.IndexOf(",") != -1)
{
string[] strArray = excludeArray.Split(",".ToCharArray());
NameValueCollection filtered = new NameValueCollection();
filtered.Add(HttpUtility.ParseQueryString(Request.Url.Query));
if (filtered.HasKeys())
{
foreach (string strMatch in strArray)
{
filtered.Remove(strMatch);
}
retQueryString = filtered.ToString(); //Here I am not able to convert back to querystring, however there are other ways to get it like (http://leekelleher.com/2008/06/06/how-to-convert-namevaluecollection-to-a-query-string/), is there any other way to do that
}
}
return retQueryString;
}
Below is the perfect solution I got it, any comments on this.
string excludeList = "cid,intcid,del";
string getFinalString = Regex.Replace(Regex.Replace(Regex.Replace(Request.Url.Query, #"^\?", "&"), "&(" + excludeList.Replace(",", "|") + ")=[^&]*", "", RegexOptions.IgnoreCase), "^&", "?");
We cannot delete a query string directly like below:
Request.QueryString.Remove("foo")
If you do this, you will get an error - collection is read-only. So, we need to write the below code before deleting the query string.
In C#:
PropertyInfo isreadonly =
typeof(System.Collections.Specialized.NameValueCollection).GetProperty(
"IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
// make collection editable
isreadonly.SetValue(this.Request.QueryString, false, null);
// remove
this.Request.QueryString.Remove("foo");
Hope this will help you !!
yes there is a way to compare two arrays
var array1 = new byte[] { 1, 2, 5, 4 };
var array2 = new byte[] { 1, 2, 3, 4 };
var areEqual = array1.SequenceEqual(array2); //return boolean value True or False

How do i use LinqToExcel to get cell values contained in the excel file

I am using this code to retrieve the receipient name and receipient number but the recpt.receipient_name and recpt.receipient_number are null.
The excel table is of this format
Name Number
andrew 1223
james 12223
dave 454545
//select names from the excel file with specified sheet name
var receipients = from n in messages.Worksheet<BulkSmsModel>(sheetName)
select n;
foreach (var recpt in receipients)
{
BulkSms newRecpt = new BulkSms();
if (recpt.receipient_number.Equals("") == true || recpt.receipient_number == 0)
{
continue;
}
newRecpt.receipient_name = recpt.receipient_name;
newRecpt.receipient_number = Int32.Parse(recpt.receipient_number.ToString());
IBsmsRepo.insertReceipient(newRecpt);
IBsmsRepo.save();
}
After some research I found a way to get the value from excel file with LinqToExcel and get the list of all Cells. Check this MVC C# Sample.
using LinqToExcel;
using Syncfusion.Olap.Reports;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.OleDb;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace YourProject.Controllers
{
public class DefaultController : Controller
{
// GET: Default1
public ActionResult Index()
{
return View();
}
public dynamic UploadExcel(HttpPostedFileBase FileUpload)
{
string PathToyurDirectory = ConfigurationManager.AppSettings["Path"].ToString();//This can be in Anywhere, but you have to create a variable in WebConfig AppSettings like this <add key="Path" value="~/Doc/"/> This directory in my case is inside App whereI upload the files here, and I Delete it after use it ;
if (FileUpload.ContentType == "application/vnd.ms-excel"
|| FileUpload.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|| FileUpload.ContentType == "application/vnd.ms-excel.sheet.binary.macroEnabled.12"
)
{
string filename = FileUpload.FileName;
string PathToExcelFile = Server.MapPath(PathToyurDirectory + filename);
// string targetpath = ;
FileUpload.SaveAs(PathToyurDirectory);
var connectionString = string.Empty;
string sheetName = string.Empty;
yourmodel db = new yourmodel();
Employee Employee = New Employee(); //This is your class no matter What.
try
{
if (filename.EndsWith(".xls") || filename.EndsWith(".csv") || filename.EndsWith(".xlsx") || filename.EndsWith(".xlsb"))
{
connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";", PathToExcelFile);
sheetName = GetTableName(connectionString);
}
var ExcelFile = new ExcelQueryFactory(PathToExcelFile);
var Data = ExcelFile.Worksheet(sheetName).ToList();
foreach (var item in Data)
{
//if yout excel file does not meet the class estructure.
Employee = new Employee
{
Name = item[1].ToString(),
LastName = item[2].ToString(),
Address = item[3].ToString(),
Phone = item[4].ToString(),
CelPghone = item[5].ToString()
};
db.Employee.Add(Employee);
db.SaveChanges();
}
}
catch (Exception)
{
throw;
}
}
return View();
}
private string GetTableName(string connectionString)
{
// You can return all Sheets for a Dropdown if you want to, for me, I just want the first one;
OleDbConnection oledbconn = new OleDbConnection(connectionString);
oledbconn.Open();
// Get the data table containg the schema guid.
var dt = oledbconn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
var sheet = dt.Rows[0]["TABLE_NAME"].ToString().Replace("$", string.Empty);
oledbconn.Close();
return sheet;
}
}
}
Since the property names on the BulkSmsModel class do not correlate directly to the column names in the spreadsheet, you will need to map the property names to the column names.
Assuming messages is the ExcelQueryFactory object, this would be the code.
var messages = new ExcelQueryFactory("excelFileName");
messages.AddMapping<BulkSmsModel>(x => x.receipient_name, "Name");
messages.AddMapping<BulkSmsModel>(x => x.receipient_number, "Number");
var receipients = from n in messages.Worksheet<BulkSmsModel>(sheetName)
select n;

Resources