I have an ASP.NET MVC application where the database is on an IBM i-Series server. I have the application development close to completion when I started to get a The ConnectionString property is invalid. error popping up:
only at log on
after the first successful log on after rebuilding
anyone logged on can still work normally
Also, note that this problem only shows up for one project in my solution. The other project uses the exact same connection string and doesn't have this problem (copied and pasted to be 100% sure). I am in active development on these projects, but have not touched the connections strings nor worked with the AccountController and related model classes after getting the login working.
I am using Visual Studio 2008 and .NET version 3.5.
Connection String:
<connectionStrings>
<add name="IbmIConnectionString" connectionString="DataSource=192.168.50.200;DefaultCollection=QMFILES;Naming=sql;UserID=XXX;Password=XXXX;"/>
</connectionStrings>
Account Controller Logon method:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
string fullName = String.Empty;
string employeeId = String.Empty;
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
EmployeeLoginModel elm = new EmployeeLoginModel();
elm.GetUserInfo(model.UserName, model.Password, out fullName, out employeeId);
// Update the AuthCookie to include the last 4 digits of the SSN.
string userDataString = String.Format("{0}|{1}|{2}", model.Password, fullName.Trim(), employeeId.Trim());
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(model.UserName, model.RememberMe);
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, userDataString);
authCookie.Value = FormsAuthentication.Encrypt(newTicket);
Response.Cookies.Add(authCookie);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Employee Login Model:
public class EmployeeLoginModel
{
public string UserName { set; get; }
public string Password { set; get; }
private iDB2Connection conn;
/// <summary>
/// Initializes a new instance of the <see cref="EmployeeLoginModel"/> class.
/// </summary>
public EmployeeLoginModel()
{
conn = new iDB2Connection(ConfigurationManager.ConnectionStrings["IbmIConnectionString"].ConnectionString);
}
/// <summary>
/// Determines whether [is valid user] [the specified username].
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
/// <returns>
/// <c>true</c> if [is valid user] [the specified username]; otherwise, <c>false</c>.
/// </returns>
public bool IsValidUser(string username, string password)
{
int count = 0;
// Get the data from the iSeries
using (conn)
{
string sqlStatement = "SELECT COUNT(XXXXX) FROM XXXXX WHERE UPPER(XXXXXX) = #1 AND XXXXXX = #2";
iDB2Command cmd = new iDB2Command(sqlStatement, conn);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#1", username.ToUpper());
cmd.Parameters.Add("#2", password);
conn.Open();
count = (Int32)cmd.ExecuteScalar();
conn.Close();
}
return ((count == 0) ? false : true);
}
Another very trivial reason for getting this error is, that the required DB2 drivers are not installed.
The inner exception stated
Unable to load DLL 'cwbdc.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
Type: System.DllNotFoundException
After posting this, I had a theory. I was switching between browsers getting things setup for a demo. I changed my method to:
public bool IsValidUser(string username, string password)
{
int count = 0;
// Get the data from the iSeries
using (iDB2Connection conn = new iDB2Connection(ConfigurationManager.ConnectionStrings["IbmIConnectionString"].ConnectionString))
{
string sqlStatement = "SELECT COUNT(XXXXXX) FROM XXXXXX WHERE UPPER(XXXXXX) = #1 AND XXXXXX = #2";
iDB2Command cmd = new iDB2Command(sqlStatement, conn);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#1", username.ToUpper());
cmd.Parameters.Add("#2", password);
conn.Open();
count = (Int32)cmd.ExecuteScalar();
conn.Close();
}
return ((count == 0) ? false : true);
}
It seems to be working now. I wonder if that was the problem.
I think because you use the connection outside the using statement, so it will be closed after go to other function, so when you call in IsValidUser, it will throw exception. in the second code, you use it in using statement, after call it will be Garbage Collection released. And it is work.
Related
We had security threat issue when scanning applications in Veracode. Got "External Control of System or Configuration Setting (CWE ID 15)".
Scan reported for using (var connection = new SqlConnection(connectionString))
we are checking whether "SQLConnectionExists" by passing connection string,
string sqlConnString = SqlHelper.GetSQLConnectionString(input.ServerName, dbName, isWinAuth, input.UserName, input.Password);
if (!DBUtil.CheckSQLConnectionExists(sqlConnString))
{
_ValidationMessage += "Database Unreachable \n";
isValid = false;
}
public static bool CheckSQLConnectionExists(string connectionString)
{
bool isExist = false;
try
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
connection.Close();
isExist = true;
}
}
catch (Exception ex)
{
Logger.Instance.Log(LogLevel.EXCEPTION, "CheckSQLConnectionExists Exception : " + ex.Message);
}
return isExist;
}
public static string GetSQLConnectionString(string servername, string db, bool isWinAuth, string username, string password)
{
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
builder["Data Source"] = servername;
builder["Initial Catalog"] = db;
if (isWinAuth)
{
builder["Integrated Security"] = "SSPI";
builder["Trusted_Connection"] = "Yes";
}
else
{
builder["Persist Security Info"] = false;
builder["User ID"] = username;
builder["Password"] = password;
}
return builder.ConnectionString;
}
In this line using (var connection = new SqlConnection(connectionString)) we got error in security scan. Could you please some one provide suggestions to resolve this Veracode error.
Veracode detects input.ServerName, input.UserName and input.Password to be user-controlled which is a risk.
Ensure validation is implemented - if possible, compare against a whitelist or known predefined server names. Also, check if the entered (injected) Min Pool Size is larger than expected. Use framework classes such as the one that you used SqlConnectionStringBuilder
Propose this check as a mitigation afterwards.
I knew that I am re-inventing the wheel. But still, I have to do it as I am instructed to do so :D.
I have to log all unhandled exception of my asp.net website. I am able to dynamically catch all exceptions but I am not able to retrieve the actual class and method name.
Everytime I got Global_asax as class name and Application_Error as the method name. Below is my code.
/// <summary>
/// Determines the log type and saves log to database. Use logtype 1 for exception logging
/// and 2 for normal audit trail.
/// </summary>
/// <param name="obj">Type of object. Accepts exception or audit log string.</param>
/// <param name="logType">Type of logging. Use LogTypes.Exception for Exception and LogTypes.Audit for Normal Logging</param>
/// <param name="fileName"></param>
/// <param name="userId">optional parameter. Accepts userid as integer</param>
/// <param name="userName">optional parameter. Accepts username as string</param>
/// <param name="memberName"></param>
[MethodImpl(MethodImplOptions.NoInlining)]
private void Log( LogTypes logType, object obj, string memberName,string fileName, int userId = 0, string userName = "")
{
var appLog = new ApplicationLog();
var stackFrame = new StackFrame(2,true);
try
{
var isHosted = HostingEnvironment.IsHosted;
appLog.UserId = userId;
appLog.UserName = userName;
appLog.InstanceName = ConfigurationSettingsHelper.InstanceName;
appLog.LoggedOn = DateTime.UtcNow;
if (isHosted)
{
appLog.ProjectName = HostingEnvironment.ApplicationHost.GetSiteName();
appLog.FilePath = HttpContext.Current.Request.RawUrl;
}
else
{
appLog.ProjectName= Assembly.GetCallingAssembly().GetName().Name;
appLog.FilePath = fileName;
}
if (logType == LogTypes.Exception)
{
appLog.LogType = 1;
if (obj is Exception ex)
{
var declaringType = ex.TargetSite.DeclaringType;
if (declaringType != null)
{
appLog.ClassName = declaringType.FullName;
appLog.MethodName = ex.TargetSite.Name;
}
appLog.LogDetails = ex.ToString();
appLog.Message = ex.Message;
}
else
{
appLog.ClassName = stackFrame.GetMethod().DeclaringType.AssemblyQualifiedName;
appLog.MethodName = memberName;
appLog.LogDetails = obj.ToString();
appLog.Message = "User defined custom exception";
}
}
else
{
appLog.LogType = 2;
appLog.ClassName = stackFrame.GetMethod().DeclaringType.AssemblyQualifiedName;
appLog.MethodName = memberName;
appLog.LogDetails = obj.ToString();
appLog.Message = "User defined custom exception";
}
}
catch (Exception ex)
{
//In case of unhandled exceptions.Try logging internal exception once.
//If failed, pass by silently.
try
{
appLog = new ApplicationLog
{
UserId = userId,
UserName = userName,
FilePath = new StackFrame(1).GetFileName(),
Message = ex.Message,
InstanceName = ConfigurationSettingsHelper.InstanceName,
ProjectName = Assembly.GetCallingAssembly().GetName().Name,
LoggedOn = DateTime.UtcNow,
LogType = 1,
LogDetails = ex.ToString()
};
if (ex.TargetSite.DeclaringType != null)
appLog.ClassName = ex.TargetSite.DeclaringType.FullName;
appLog.MethodName = ex.TargetSite.Name;
}
finally
{
HttpWebMethods.PostAsync(ConfigurationSettingsHelper.LoggerApiBaseAddress,
ConfigurationSettingsHelper.SaveLogEndpoint, appLog);
} // intentionally eating exception}
}
finally
{
HttpWebMethods.PostAsync(ConfigurationSettingsHelper.LoggerApiBaseAddress,
ConfigurationSettingsHelper.SaveLogEndpoint, appLog);
}
}
It's logging all good at all places. But for the case of any unhandled exceptions, I need to capture the class name and method name. But instead, its giving me the global.asax details.
Its a class library and i want it work as same as Global.asax works. Automatically recognizes all errors.
Please help.
I tried to logged in localhost and everything works properly.
The code:
public static bool LoginGoogleCalendar(string clientId, string clientSecret, string idGCalendarUser, string calendarServiceScope, string folder)
{
try
{
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret,
},
new[] { calendarServiceScope },
idGCalendarUser,
CancellationToken.None, new FileDataStore(folder)).Result;
return true;
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
return false;
}
}
(I set properly the authorization for fileDataStore)
In Google Developers Console:
Redirect URIs: http://localhost/authorize/
Javascript Origins: http://localhost:8081
I use Visual Studio 2013, IIS 8
When i try the login to the server, will block the entire server for minutes and the answer after is: System.Web.HttpException Request timed out.
In Google Developers Console:
Redirect URIs: http://pippo.pluto.it/authorize/
Javascript Origins: http://pippo.pluto.it
On the server: IIS 7
The reference to my example:
https://developers.google.com/google-apps/calendar/instantiate
I walked into to same problem. Alot of examples on the internet tell you to use this class. For web applications this is not the class to use though. This class wil work perfect for "offline" applications, but when you use this class on the IIS server it wil try to open the popup on the server but it wont let it.
The class I use: GoogleAuthorizationCodeFlow
using Google.Apis.Analytics.v3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Web;
using Google.Apis.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace GoogleOauth2DemoWebApp
{
public class GoogleOauth
{
public AnalyticsService Handle(string _userId, string _connectionString, string _googleRedirectUri, string _applicationName, string[] _scopes)
{
try
{
string UserId = _userId;//The user ID wil be for examlpe the users gmail address.
AnalyticsService service;
GoogleAuthorizationCodeFlow flow;
//use extended class to create google authorization code flow
flow = new ForceOfflineGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
DataStore = new DbDataStore(_connectionString),//DataStore class to save the token in a SQL database.
ClientSecrets = new ClientSecrets { ClientId = "XXX-YOUR CLIENTID-XXX", ClientSecret = "XXX-YOURCLIENTSECRET-XXX" },
Scopes = _scopes,
});
var uri = HttpContext.Current.Request.Url.ToString();
string redirecturi = _googleRedirectUri;//This is the redirect URL set in google developer console.
var code = HttpContext.Current.Request["code"];
if (code != null)
{
var token = flow.ExchangeCodeForTokenAsync(UserId, code,
uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result;
var test = HttpContext.Current.Request["state"];
// Extract the right state.
var oauthState = AuthWebUtility.ExtracRedirectFromState(
flow.DataStore, UserId, HttpContext.Current.Request["state"]).Result;
HttpContext.Current.Response.Redirect(oauthState);
}
else
{
var result = new AuthorizationCodeWebApp(flow, redirecturi, uri).AuthorizeAsync(UserId,
CancellationToken.None).Result;
if (result.RedirectUri != null)
{
// Redirect the user to the authorization server.
HttpContext.Current.Response.Redirect(result.RedirectUri);
}
else
{
// The data store contains the user credential, so the user has been already authenticated.
service = new AnalyticsService(new BaseClientService.Initializer()
{
HttpClientInitializer = result.Credential,
ApplicationName = _applicationName
});
return service;
}
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
{
var ss = new Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl));
ss.AccessType = "offline";
ss.ApprovalPrompt = "force";
ss.ClientId = ClientSecrets.ClientId;
ss.Scope = string.Join(" ", Scopes);
ss.RedirectUri = redirectUri;
return ss;
}
};
}
}
Also I user a DataStore class. Saving the tokens to a file on you server isnt the best practice. I used a SQL database.
Example of the datastore class. It will make a table for you, not the best way but for testing perpose good enough.
using Google.Apis.Json;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GoogleOauth2DemoWebApp
{
public class DbDataStore : IDataStore
{
readonly string connectionString;
public string ConnectionString { get { return connectionString; } }
private Boolean _ConnectionExists { get; set; }
public Boolean connectionExists { get { return _ConnectionExists; } }
/// <summary>
/// Constructs a new file data store with the specified folder. This folder is created (if it doesn't exist
/// yet) under the current directory
/// </summary>
/// <param name="folder">Folder name</param>
public DbDataStore(String _connectionString)
{
connectionString = _connectionString;
SqlConnection myConnection = this.connectdb(); // Opens a connection to the database.
if (_ConnectionExists)
{
// check if the Table Exists;
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select 1 from GoogleUser where 1 = 0",
myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
var hold = myReader["Column1"];
}
}
catch
{
// table doesn't exist we create it
SqlCommand myCommand = new SqlCommand("CREATE TABLE [dbo].[GoogleUser]( " +
" [username] [nvarchar](4000) NOT NULL," +
" [RefreshToken] [nvarchar](4000) NOT NULL," +
" [Userid] [nvarchar](4000) NOT NULL" +
" ) ON [PRIMARY]", myConnection);
myCommand.ExecuteNonQuery();
}
}
myConnection.Close();
}
/// <summary>
/// Stores the given value for the given key. It creates a new file (named <see cref="GenerateStoredKey"/>) in
/// <see cref="FolderPath"/>.
/// </summary>
/// <typeparam name="T">The type to store in the data store</typeparam>
/// <param name="key">The key</param>
/// <param name="value">The value to store in the data store</param>
public Task StoreAsync<T>(string key, T value)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
SqlConnection myConnection = this.connectdb();
if (!_ConnectionExists)
{
throw new Exception("Not connected to the database");
}
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select Userid from GoogleUser where UserName = #username", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string hold = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
hold = myReader["Userid"].ToString();
}
myReader.Close();
if (hold == null)
{
try
{
// New User we insert it into the database
string insertString = "INSERT INTO [dbo].[GoogleUser] ([username],[RefreshToken],[Userid]) " +
" VALUES (#key,#value,'1' )";
SqlCommand commandins = new SqlCommand(insertString, myConnection);
commandins.Parameters.AddWithValue("#key", key);
commandins.Parameters.AddWithValue("#value", serialized);
commandins.ExecuteNonQuery();
}
catch (Exception ex)
{
throw new Exception("Error inserting new row: " + ex.Message);
}
}
else
{
try
{
// Existing User We update it
string insertString = "update [dbo].[GoogleUser] " +
" set [RefreshToken] = #value " +
" where username = #key";
SqlCommand commandins = new SqlCommand(insertString, myConnection);
commandins.Parameters.AddWithValue("#key", key);
commandins.Parameters.AddWithValue("#value", serialized);
commandins.ExecuteNonQuery();
}
catch (Exception ex)
{
throw new Exception("Error updating user: " + ex.Message);
}
}
}
myConnection.Close();
return TaskEx.Delay(0);
}
/// <summary>
/// Deletes the given key. It deletes the <see cref="GenerateStoredKey"/> named file in <see cref="FolderPath"/>.
/// </summary>
/// <param name="key">The key to delete from the data store</param>
public Task DeleteAsync<T>(string key)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
SqlConnection myConnection = this.connectdb();
if (!_ConnectionExists)
{
throw new Exception("Not connected to the database");
}
// Deletes the users data.
string deleteString = "delete from [dbo].[GoogleUser] " +
"where username = #key";
SqlCommand commandins = new SqlCommand(deleteString, myConnection);
commandins.Parameters.AddWithValue("#key", key);
commandins.ExecuteNonQuery();
myConnection.Close();
return TaskEx.Delay(0);
}
/// <summary>
/// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
/// in <see cref="FolderPath"/> doesn't exist.
/// </summary>
/// <typeparam name="T">The type to retrieve</typeparam>
/// <param name="key">The key to retrieve from the data store</param>
/// <returns>The stored object</returns>
public Task<T> GetAsync<T>(string key)
{
//Key is the user string sent with AuthorizeAsync
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
// Note: create a method for opening the connection.
SqlConnection myConnection = new SqlConnection(this.ConnectionString);
myConnection.Open();
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = #username;", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string RefreshToken = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
RefreshToken = myReader["RefreshToken"].ToString();
}
if (RefreshToken == null)
{
// we don't have a record so we request it of the user.
tcs.SetResult(default(T));
}
else
{
try
{
// we have it we use that.
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(RefreshToken));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
}
return tcs.Task;
}
/// <summary>
/// Clears all values in the data store. This method deletes all files in <see cref="FolderPath"/>.
/// </summary>
public Task ClearAsync()
{
SqlConnection myConnection = this.connectdb();
if (!_ConnectionExists)
{
throw new Exception("Not connected to the database");
}
// Removes all data from the Table.
string truncateString = "truncate table [dbo].[GoogleUser] ";
SqlCommand commandins = new SqlCommand(truncateString, myConnection);
commandins.ExecuteNonQuery();
myConnection.Close();
return TaskEx.Delay(0);
}
/// <summary>Creates a unique stored key based on the key and the class type.</summary>
/// <param name="key">The object key</param>
/// <param name="t">The type to store or retrieve</param>
public static string GenerateStoredKey(string key, Type t)
{
return string.Format("{0}-{1}", t.FullName, key);
}
//Handel's creating the connection to the database
private SqlConnection connectdb()
{
SqlConnection myConnection = null;
try
{
myConnection = new SqlConnection(this.ConnectionString);
try
{
myConnection.Open();
// ensuring that we are able to make a connection to the database.
if (myConnection.State == System.Data.ConnectionState.Open)
{
_ConnectionExists = true;
}
else
{
throw new ArgumentException("Error unable to open connection to the database.");
}
}
catch (Exception ex)
{
throw new ArgumentException("Error opening Connection to the database: " + ex.Message);
}
}
catch (Exception ex)
{
throw new ArgumentException("Error creating Database Connection: " + ex.Message);
}
return myConnection;
}
}
}
using the class:
GoogleOauth g = new GoogleOauth();
AnalyticsService service = g.Handle(userEmailAddress,
connectionString, redirectUrl,
"YOURAPLICATIONNAME",
new[] {AnalyticsService.Scope.AnalyticsReadonly});
DataResource.RealtimeResource.GetRequest request = service.Data.Realtime.Get(String.Format("ga:{0}", profileId), "rt:activeUsers");
RealtimeData feed = request.Execute();
If people are intrested I can upload a sample project to github.
I implemented my custom IDataStore so that I can store End User Tokens on my database instead of the default implementation, which is saved on FileSystem within %AppData%.
public class GoogleIDataStore : IDataStore
{
...
public Task<T> GetAsync<T>(string key)
{
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
var user = repository.GetUser(key.Replace("oauth_", ""));
var credentials = repository.GetCredentials(user.UserId);
if (key.StartsWith("oauth") || credentials == null)
{
tcs.SetResult(default(T));
}
else
{
var JsonData = Newtonsoft.Json.JsonConvert.SerializeObject(Map(credentials));
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(JsonData));
}
return tcs.Task;
}
}
Controller
public async Task<ActionResult> AuthorizeDrive(CancellationToken cancellationToken)
{
var result = await new AuthorizationCodeMvcApp(this, new GoogleAppFlowMetadata()).
AuthorizeAsync(cancellationToken);
if (result.Credential == null)
return new RedirectResult(result.RedirectUri);
var driveService = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = result.Credential,
ApplicationName = "My app"
});
//Example how to access drive files
var listReq = driveService.Files.List();
listReq.Fields = "items/title,items/id,items/createdDate,items/downloadUrl,items/exportLinks";
var list = listReq.Execute();
return RedirectToAction("Index", "Home");
}
The issue happens on the redirect event. After that first redirect it works fine.
I found out that something is different on the redirect event. On the redirect event the T is not a Token Response, but a string. Also, the key is prefixed with "oauth_".
So I assume that I should return a different result on the redirect, but I have no clue what to return.
The error I get is : Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"State is invalid", Description:"", Uri:""
Google Source Code Reference
https://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis.DotNet4/Apis/Util/Store/FileDataStore.cs?r=eb702f917c0e18fc960d077af132d0d83bcd6a88
https://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis.Auth/OAuth2/Web/AuthWebUtility.cs?r=eb702f917c0e18fc960d077af132d0d83bcd6a88
Thanks for your help
I am not exactly sure why yours isnt working but this is a copy of the code i use. The full class can be found here DatabaseDatastore.cs
/// <summary>
/// Returns the stored value for the given key or <c>null</c> if the matching file (<see cref="GenerateStoredKey"/>
/// in <see cref="FolderPath"/> doesn't exist.
/// </summary>
/// <typeparam name="T">The type to retrieve</typeparam>
/// <param name="key">The key to retrieve from the data store</param>
/// <returns>The stored object</returns>
public Task<T> GetAsync<T>(string key)
{
//Key is the user string sent with AuthorizeAsync
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException("Key MUST have a value");
}
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
// Note: create a method for opening the connection.
SqlConnection myConnection = new SqlConnection("user id=" + LoginName + ";" +
#"password=" + PassWord + ";server=" + ServerName + ";" +
"Trusted_Connection=yes;" +
"database=" + DatabaseName + "; " +
"connection timeout=30");
myConnection.Open();
// Try and find the Row in the DB.
using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = #username;", myConnection))
{
command.Parameters.AddWithValue("#username", key);
string RefreshToken = null;
SqlDataReader myReader = command.ExecuteReader();
while (myReader.Read())
{
RefreshToken = myReader["RefreshToken"].ToString();
}
if (RefreshToken == null)
{
// we don't have a record so we request it of the user.
tcs.SetResult(default(T));
}
else
{
try
{
// we have it we use that.
tcs.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(RefreshToken));
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
}
return tcs.Task;
}
The API stores (at least) two values in your IDataStore. Here is what the authorization process looks like from an empty IDataStore's point of view (note which lines set a value and which lines get a value):
Getting IDataStore value: MyKey <= null
Setting IDataStore value: oauth_MyKey => "http://localhost..."
Setting IDataStore value: MyKey => {"access_token":"...
Getting IDataStore value: oauth_MyKey <= "http://localhost..."
Getting IDataStore value: MyKey <= {"access_token":"...
At first, the API tries to find a stored access_token, but there is none in the data store (which just returns null), and the API starts the authorization process. The "oauth_..." key is some state info the API needs during this process, and is normally set before it is retrieved (in my experience).
However, if your IDataStore never received a value with an "oauth_.." key, and thus has nothing to return, simply return null, and the API should create a new one when needed.
I have asp.net mvc4 project, where have database with students, also have old database in .xls format and I need to migrate all values from old database into new one sql server database. In my mvc project I have membership controller which include method for Register new student. Also I'm write console application which parse .xls table and insert all values into my new database via Register method.
Console application:
static void Main(string[] args)
{
string con = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\MigrateExelSql\Include\TestDb.xlsx; Extended Properties=Excel 12.0;";
MembershipController mc = new MembershipController();
Student student = new Student();
student.Username = null;
student.Password = "password";
student.Email = null;
student.EntryYear = 2014;
student.PassportNumber = 0;
student.IsApproved = true;
student.PasswordFailuresSinceLastSuccess = 0;
student.IsLockedOut = false;
using(OleDbConnection connection = new OleDbConnection(con))
{
connection.Open();
OleDbCommand command = new OleDbCommand("select * from [Sheet1$]", connection);
using(OleDbDataReader dr = command.ExecuteReader())
{
while(dr.Read())
{
string row1Col0 = dr[0].ToString();
Console.WriteLine(row1Col0);
string row1Col1 = dr[1].ToString();
Console.WriteLine(row1Col1);
Console.WriteLine();
student.Username = row1Col0;
student.Email = row1Col1;
try
{
mc.Register(student);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Console.ReadKey();
}
Register method
public static MembershipCreateStatus Register(string Username, string Password, string Email, bool IsApproved, string FirstName, string LastName)
{
MembershipCreateStatus CreateStatus;
System.Web.Security.Membership.CreateUser(Username, Password, Email, null, null, IsApproved, null, out CreateStatus);
if (CreateStatus == MembershipCreateStatus.Success)
{
using (UniversityContext Context = new UniversityContext(ConfigurationManager.ConnectionStrings[0].ConnectionString))
{
Student User = Context.Students.FirstOrDefault(Usr => Usr.Username == Username);
User.FirstName = FirstName;
User.LastName = LastName;
Context.SaveChanges();
}
if (IsApproved)
{
FormsAuthentication.SetAuthCookie(Username, false);
}
}
return CreateStatus;
}
ActionResult POST
public ActionResult Register(Student student)
{
Register(student.Username, student.Password, student.Email, true, student.FirstName, student.LastName);
return RedirectToAction("Index", "Membership");
}
Everything work fine when I try to add students from web application, but when I try to add from my parsed database it was get the error on the next line
System.Web.Security.Membership.CreateUser(Username, Password, Email, null, null, IsApproved, null, out CreateStatus);
in my Register method, that invalidAnswer. I'm change null to "123456789", then next error will be invalidQuestion, then I'm also change from null to "123456789". And after this it's tell me that my invalidPassword. Also I'm added next line into my membership provider's line in my web.config requiresQuestionAndAnswer="false".
I have no idea why it's not working. Does anybody have any ideas?
Whenever I'm required to do anything like import data from spreadsheets like this simply write an Importer console app in my solution. I also use LINQ to CSV which you can get from Nuget and its a really useful tool to use.
It allows you to read in the data from your spreadsheet into the relevant class objects, and from there once you have validated each object you can simply create new objects in your Database using your Data Layer.
Since xls (not xlsx) files are basically text files in which contents are separated by usually a tab character (or maybe some certain spercial charchters) a better approach would be to read all the lines in the file and store them in a list.
Then you can split each element at the time you are inserting them in your database. This can be easily done using a foreach loop like:
foreach (var i in xlsList) {
String s [] = i.Split('\t').ToArray(); // refer to your file
for (int j = 0; j < s.lenght; j++) {
Your SQL statement in here
}
}