Setting up AIML in asp.net MVC (FormatException error) - asp.net-mvc

Total noob when it comes to using AIML and having a really hard time getting this set up for an asp.net mvc webpage. I have a basic view setup that the user can enter a message in a textbox and I'm trying to get the chatbot to return a response. I've gotten that interaction to work with my text case so I know the function is correctly getting the users response and that I can send back a response and show it in the chatbox, my problem is trying to setup the chatbot to create dynamic responses. Right now in my controller I have:
String filePath = Server.MapPath("~/aimlBot/aiml/");
ChatBot catbot = new ChatBot(filePath);
string ReturnText = catbot.GetOutput(text); //text is just a string no html or fancy stuff in it
and my ChatBot class
Public class ChatBot : Bot
{
private Bot myBot;
private User myUser;
public ChatBot(string filepath)
{
myBot = new Bot();
myUser = new User("Human", myBot);
Initialize(filepath);
}
private void Initialize(string filepath)
{
AIMLbot.Utils.AIMLLoader loader = new AIMLbot.Utils.AIMLLoader(this.myBot);
myBot.isAcceptingUserInput = false;
loader.loadAIML(filepath);
myBot.isAcceptingUserInput = true;
}
public String GetOutput(String input)
{
Request r = new Request(input, myUser, myBot);
Result res = myBot.Chat(r); //breaks here
string response = "Bot: " + res.Output;
return (response);
}
}
the problem I'm getting is at the
Result res = myBot.Chat(r);
the program throws a FormatException
System.FormatException was unhandled by user code
Message=Input string was not in a correct format.
Source=mscorlib
StackTrace:
at System.Number.ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt)
at System.Convert.ToDouble(String value)
at AIMLbot.Bot.get_TimeOut()
at AIMLbot.Utils.Node.evaluate(String path, SubQuery query, Request request, MatchState matchstate, StringBuilder wildcard)
at AIMLbot.Bot.Chat(Request request)
at Ira.aimlBot.ChatBot.GetOutput(String input) in C:\Users\Ira\Documents\Visual Studio 2010\Projects\Ira\Ira\aimlBot\ChatBot.cs:line 36
at Ira.Controllers.ARGController.Speak(String text) in C:\Users\Ira\Documents\Visual Studio 2010\Projects\Ira\Ira\Controllers\ARGController.cs:line 35
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
InnerException:
I have No idea what is wrong with my code. I've tried even changing it from the variable string to just a hardcode case like "Hello how are you" which still caused the same exception.

You have everything perfect except the loadSettings function. Please refer the below snippet to clear your problem!
public ChatBot(string filepath)
{
myBot = new Bot();
myBot.loadSettings(); // <----- You have to insert this line to fix the error!
myUser = new User("Human", myBot);
Initialize(filepath);
}

Related

Xamarin iOS System.FormatException: Input string was not in a correct format

I'm facing a weird issue in iOS 13.3 and 13.4 that having System.FormatException for some users only. The app is develop using Xamarin Forms.
The error happen after calling to backend API to get user profile but before reaching the backend API (verified not reaching because AppInsights trace logs is not showing the call).
I have check the places where the error might be happening but have no clue.
Exception Stack Trace recorded in AppCenter
System.FormatException: Input string was not in a correct format.
System.Text StringBuilder.FormatError ()
System.Text StringBuilder.AppendFormatHelper (System.IFormatProvider provider, System.String format, System.ParamsArray args)
System String.FormatHelper (System.IFormatProvider provider, System.String format, System.ParamsArray args)
System String.Format (System.String format, System.Object[] args)
Mobile.Services ApiService.GetAsync[T] (Wipro.MyBAT.Mobile.Core.Logging.AnalyticsEvent analyticsEvent, System.String endPoint, System.String queryString, System.Boolean requiresAuthentication, System.Threading.CancellationToken cancelToken, System.Boolean withRetry)
Mobile.Services ApiService.GetUserProfile ()
Mobile.Services.Users UserService.GetUserProfileFromServer ()
Get User Profile method
public async Task<Response<Common.Model.User>> GetUserProfile()
{
var result = await GetAsync<Response<Common.Model.User>>(AnalyticsEvent.UserProfilePerformance, Endpoints.PROFILE).ConfigureAwait(false);
return result;
}
Get User Profile method
private async Task<T> GetAsync<T>(AnalyticsEvent analyticsEvent, string endPoint, string queryString = "", bool requiresAuthentication = true, CancellationToken cancelToken = default, bool withRetry = true)
where T : new()
{
Stopwatch stopwatch = new Stopwatch();
var dict = new Dictionary<string, string>
{
{ "Throttler count", _throttler.CurrentCount.ToString() },
{ "Throttler limit", THROTTLER_LIMIT.ToString() },
{ "Retry", (!withRetry).ToString() }
};
await _throttler.WaitAsync();
stopwatch.Start();
string callId = System.Guid.NewGuid().ToString();
string url;
string responseString = string.Empty;
try
{
if (_connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None || _connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.Unknown)
{
return default(T);
}
url = $"{_environment.HostUrl}/api/{endPoint}{queryString}";
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, url);
if (requiresAuthentication)
{
var token = await _authService.GetAccessToken();
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);
message.Headers.Add("callid", callId);
}
// Error should be before this line as the call it not reaching API side
HttpResponseMessage response = await _httpClient.SendAsync(message, cancelToken);
Finally found the root cause of the problem. It is actually calling to the API server but is throwing exception before leaving mobile due to the user is having some VPN in the wifi network. Changing to use 4G instead of Wifi solve the problem.
The String.Format issue is due to the exception handling code using string.Format incorrectly. This makes the actual issue cover up by the string.format exception.
2 things learned:
Always check first if using another network solve the problem or not
Handle exception correctly

What is the order of execution of filters used Globally at ASP.NET MVC 5?

In asp.net mvc 5, If the following custom filters(authorization, exception) added globally, then specify the order of execution
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CPExceptionHandler());
filters.Add(new LogonAuthorizeAttribute());
}
I tried to understand the order of execution of filters globally from the link
msdn, but unable to grasp information. Kindly help me to clarify regarding this, what is the order of execution of global filters such as Authorization, exception etc.,?
In MVC the order of Filter Execution will always be
1. Authorization filters
2. Action filters
3. Response filters
4. Exception filters
The same is applicable even if it is added Globally.
Below is the implementation of the code in MVC
if (actionDescriptor != null)
{
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
Action continuation = null;
BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
{
try
{
AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext,
filterInfo.AuthenticationFilters, actionDescriptor);
if (authenticationContext.Result != null)
{
// An authentication filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext =
InvokeAuthenticationFiltersChallenge(controllerContext,
filterInfo.AuthenticationFilters, actionDescriptor, authenticationContext.Result);
continuation = () => InvokeActionResult(controllerContext,
challengeContext.Result ?? authenticationContext.Result);
}
else
{
AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
if (authorizationContext.Result != null)
{
// An authorization filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext =
InvokeAuthenticationFiltersChallenge(controllerContext,
filterInfo.AuthenticationFilters, actionDescriptor, authorizationContext.Result);
continuation = () => InvokeActionResult(controllerContext,
challengeContext.Result ?? authorizationContext.Result);
}
else
{
if (controllerContext.Controller.ValidateRequest)
{
ValidateRequest(controllerContext);
}
IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
IAsyncResult asyncResult = BeginInvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters, asyncCallback, asyncState);
continuation = () =>
{
ActionExecutedContext postActionContext = EndInvokeActionMethodWithFilters(asyncResult);
// The action succeeded. Let all authentication filters contribute to an action
// result (to combine authentication challenges; some authentication filters need
// to do negotiation even on a successful result). Then, run this action result.
AuthenticationChallengeContext challengeContext =
InvokeAuthenticationFiltersChallenge(controllerContext,
filterInfo.AuthenticationFilters, actionDescriptor,
postActionContext.Result);
InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,
challengeContext.Result ?? postActionContext.Result);
};
return asyncResult;
}
}
}
catch (ThreadAbortException)
{
// This type of exception occurs as a result of Response.Redirect(), but we special-case so that
// the filters don't see this as an error.
throw;
}
catch (Exception ex)
{
// something blew up, so execute the exception filters
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
if (!exceptionContext.ExceptionHandled)
{
throw;
}
continuation = () => InvokeActionResult(controllerContext, exceptionContext.Result);
}
return BeginInvokeAction_MakeSynchronousAsyncResult(asyncCallback, asyncState);
};
It will always executes
InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
then
InvokeAuthenticationFiltersChallenge(controllerContext,
filterInfo.AuthenticationFilters, actionDescriptor, authorizationContext.Result);
then
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
Here the Order is required only when you have same type filter multiple times

Index Out of Range Exception - Active Directory Adapter

I understand what an Index Out of Range Exception is, however, I can't seem to figure out what is going on in the Stack Trace below.
This is an asp.net website, and it has been working without issue for the past few years. I have checked with the System Administrator and they noted nothing has changed on the server hosting the website or dc. Currently at a stand still, any ideas as to where to look or begin diagnosing?
[IndexOutOfRangeException: Index was outside the bounds of the array.]
System.DirectoryServices.AccountManagement.SidList.TranslateSids(String target, IntPtr[] pSids) +1507
System.DirectoryServices.AccountManagement.SidList..ctor(SID_AND_ATTR[] sidAndAttr) +142
System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p) +220
System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroupsHelper() +50
PayDirectory.Classes.ActiveDirectoryAdapter.IsUserAllowed(String username, IList`1 allowedgroups) in C:\Users\johndoe\Documents\Visual Studio 2010\Projects\PayDirectory\PayDirectory\Classes\ActiveDirectoryAdapter.cs:35
PayDirectory.Controllers.AccountController.CheckUser(String sessionid) in C:\Users\johndoe\Documents\Visual Studio 2010\Projects\PayDirectory\PayDirectory\Controllers\AccountController.cs:42
lambda_method(Closure , ControllerBase , Object[] ) +108
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +188
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +28
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +29
Etc.
That is the beginning of the Stack Trace, I can post the entire trace if necessary.
Basically, the application takes the session id of a user logged into Joomla, checks ad to see if that user is in a particular group (Principals) and allows them to view certain content, otherwise it will state Access is Denied.
EDIT
Adding source code for "IsuserAllowed" in ActiveDirectoryAdapter class
public Boolean IsUserAllowed(string username, IList<string> allowedgroups)
{
PrincipalContext domain = new PrincipalContext(ContextType.Domain, "Redmond");
UserPrincipal user = UserPrincipal.FindByIdentity(domain, username);
List<GroupPrincipal> groups = new List<GroupPrincipal>();
if (user != null)
{
PrincipalSearchResult<Principal> authGroups = user.GetAuthorizationGroups();
foreach (Principal p in authGroups)
{
if (p is GroupPrincipal)
{
groups.Add((GroupPrincipal)p);
}
}
}
string groupstring = string.Join(",", (object[])groups.ToArray());
string[] groupnames = groupstring.Split(',');
for (int i = 0; i < allowedgroups.Count; i++)
{
if (groupnames.Contains(allowedgroups[i]))
{
return true;
}
}
return false;
}

Working twitter login turns into 401

I've had twitter login working on my site for years. I randomly decided to test it today and found out it was not working.
I am using dotnetopenauth 3.4.7.11121 . I have twitterConsumerKey and twitterConsumerSecret in my web config. Thoughts on where to troubleshoot first?
The error is "The remote server returned an error: (401) Unauthorized."
My code of note:
public static OutgoingWebResponse StartSignInWithTwitter(bool forceNewLogin)
{
var redirectParameters = new Dictionary<string, string>();
if (forceNewLogin)
{
redirectParameters["force_login"] = "true";
}
Uri callback = MessagingUtilities.GetRequestUrlFromContext().StripQueryArgumentsWithPrefix("oauth_");
var request = TwitterSignIn.PrepareRequestUserAuthorization(callback, null, redirectParameters);
return TwitterSignIn.Channel.PrepareResponse(request);
}
The exception:
[WebException: The remote server returned an error: (401) Unauthorized.]
System.Net.HttpWebRequest.GetResponse() +6442312
DotNetOpenAuth.Messaging.StandardWebRequestHandler.GetResponse(HttpWebRequest request, DirectWebRequestOptions options) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\StandardWebRequestHandler.cs:126
[ProtocolException: Error occurred while sending a direct message or getting the response.]
DotNetOpenAuth.Messaging.StandardWebRequestHandler.GetResponse(HttpWebRequest request, DirectWebRequestOptions options) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\StandardWebRequestHandler.cs:169
DotNetOpenAuth.Messaging.StandardWebRequestHandler.GetResponse(HttpWebRequest request) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\StandardWebRequestHandler.cs:100
DotNetOpenAuth.Messaging.Channel.GetDirectResponse(HttpWebRequest webRequest) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:622
DotNetOpenAuth.Messaging.Channel.RequestCore(IDirectedProtocolMessage request) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:644
DotNetOpenAuth.Messaging.Channel.Request(IDirectedProtocolMessage requestMessage) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:467
DotNetOpenAuth.Messaging.Channel.Request(IDirectedProtocolMessage requestMessage) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:447
DotNetOpenAuth.OAuth.ConsumerBase.PrepareRequestUserAuthorization(Uri callback, IDictionary`2 requestParameters, IDictionary`2 redirectParameters, String& requestToken) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ConsumerBase.cs:221
TwitterConsumer.StartSignInWithTwitter(Boolean forceNewLogin) in c:\TFSWebForms\www.nanaimo.ca\Nanaimo.Ca\openID\TwitterConsumer.cs:207
openID_login.ibTwitter_Click(Object sender, EventArgs e) in c:\TFSWebForms\www.nanaimo.ca\Nanaimo.Ca\openID\login.aspx.cs:717
System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e) +116
System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +101
System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +9643314
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724
UPDATE
I used fiddler and found that that dotnetopenauth is not forwarding the authentication when it gets redirected from http to https.
I found my issue. Twitter seems to have started forcing https and the redirect stopped working. I updated my twitter consumer to change it to https from http. My consumer was taken from the samples.
/// <summary>
/// The description of Twitter's OAuth protocol URIs for use with actually reading/writing
/// a user's private Twitter data.
/// </summary>
public static readonly ServiceProviderDescription ServiceDescription = new ServiceProviderDescription
{
RequestTokenEndpoint = new MessageReceivingEndpoint("https://twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint("https://twitter.com/oauth/authorize", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
AccessTokenEndpoint = new MessageReceivingEndpoint("https://twitter.com/oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};
/// <summary>
/// The description of Twitter's OAuth protocol URIs for use with their "Sign in with Twitter" feature.
/// </summary>
public static readonly ServiceProviderDescription SignInWithTwitterServiceDescription = new ServiceProviderDescription
{
RequestTokenEndpoint = new MessageReceivingEndpoint("https://twitter.com/oauth/request_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint("https://twitter.com/oauth/authenticate", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
AccessTokenEndpoint = new MessageReceivingEndpoint("https://twitter.com/oauth/access_token", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};
Semi related: my old timeline URL "http://twitter.com/statuses/user_timeline/14529984.xml" changed to https://api.twitter.com/1/statuses/user_timeline/14529984.xml at some point breaking another feature of my app.

To read an Excel file with ASP.Net Excel must be installed on the server?

I read an Excel file from ASP: NET MVC to localhost without problems. But when you publish the site on error. On the server is not installed the office or any Excel library. Could this be the problem?? Or could it be??.
Thanks for your answers
*Do not use any library, read the Excel file through a connection OleDbConnection. My code is is the following:
//the error occurs here, but only published on the website:
strConex = ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString;
/**strConex = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:copia.xlsx;
Extended Properties='Excel 12.0;HDR=YES;'"**/
OleDbConnection connection = new OleDbConnection(strConex);
OleDbCommand command = new OleDbCommand();
OleDbDataAdapter adapter = new OleDbDataAdapter();
command.Connection = connection;
connection.Open();
DataTable dtschema = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
String nameSheet = dtschema.Rows[0]["TABLE_NAME"].ToString();
connection.Close();
connection.Open();
command.CommandText = "SELECT * From [" + nameSheet + "]";
adapter.SelectCommand = command;
adapter.Fill(dt);
connection.Close();
The result in the following exception:
System.NullReferenceException: Object reference not set to an instance of an object. at BusinessServices.RetentionAgentService.CreateRetentionsByAgentExcel(String path, String idcard, String user, DataTable dtError, DateTime initialDate, DateTime endDate, Guid& masterId) in C:\Corp\PublicAriManagua\BusinessServices\RetentionAgent\RetentionAgentService.cs:line 342 at PublicARI.Controllers.AgentRetentionController.SaveRetentions(HttpPostedFileBase file, RetentionAgentDeclaration retAgent) in C:\Corp\PublicAriManagua\PublicARI\Controllers\AgentRetentionController.cs:line 496 at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
Just check that the dll for the reading of excel is also going up to the server bin folder. What are you using to read btw?
I am using EPPlus, it's really good, here is the example of method that exports excel sheet to DataTable:
/// <summary>
/// exports XLSX sheet to DataTable
/// </summary>
/// <param name="excelFile">Excel file</param>
/// <param name="sheetName">Sheet for export</param>
/// <param name="firstRowIsHeader">Excel first row is header</param>
/// <returns>DataTable with selected sheet data</returns>
private DataTable XlsxToDataTable(FileInfo excelFile, string sheetName, bool firstRowIsHeader)
{
ExcelPackage ePack = new ExcelPackage(excelFile);
ExcelWorksheet ws = ePack.Workbook.Worksheets[sheetName];
DataTable result = new DataTable();
/// header
for (int xx = 1; xx <= ws.Dimension.End.Column; xx++)
{
string data = "";
if (ws.Cells[1, xx].Value != null)
data = ws.Cells[1, xx].Value.ToString();
string columnName = firstRowIsHeader ? data : "Column" + xx.ToString();
result.Columns.Add(columnName);
}
/// data
int first = firstRowIsHeader ? 2 : 1;
for (int excelRow = first; excelRow <= ws.Dimension.End.Row; excelRow++)
{
DataRow rw = result.NewRow();
result.Rows.Add(rw);
for (int excelCol = 1; excelCol <= ws.Dimension.End.Column; excelCol++)
{
string data = "";
if (ws.Cells[excelRow, excelCol].Value != null)
data = ws.Cells[excelRow, excelCol].Value.ToString();
rw[excelCol-1] = data;
}
}
return result;
}

Resources