Call Membership.GetUser() from Session_Start in global.asax - ASP.NET identity - asp.net

I'm trying trying to call Membership.GetUser from from Session_Start in global.asax using ASP.NET identity 2.0
When .Create() is called I get the following erorr at Membership.GetUser:
An exception of type 'System.Data.SqlClient.SqlException' occurred in
System.Web.dll but was not handled in user code
Additional information: Could not find stored procedure
'dbo.aspnet_CheckSchemaVersion'.
I suspect this has something to do with OWIN not being initialized yet?
Does anyone know if it's possible to get the current GUID from application_start?
Here's my code...
Global.asax
protected void Session_Start(Object sender, EventArgs e)
{
SessionData.Create();
}
SessionData:
public class SessionData
{
public static void Create()
{
using (var db = new BeatBoxV2Context())
{
var membershipUser = Membership.GetUser();
var providerUserKey = membershipUser?.ProviderUserKey;
if (providerUserKey == null) return;
var guid = (Guid)providerUserKey;
var account = db.Account.Find(guid);
var sessionData = new SessionData
{
UserPermissions= db.Permissions.Where(h => h.Guid == guid).ToList()
};
}
}
public List<Permissions> UserPermissions
{
get { return HttpContext.Current.Session["UserPermissions"] != null ? (List<HolterPermission>)HttpContext.Current.Session["UserPermissions"] : null; }
set { HttpContext.Current.Session["UserPermissions"] = value; }
}
}

OK So the solution was as follows:
Attach the database in App_Data in SQL Express
Run aspnet_regsql from the VS Command Prompt

Related

Setting cookie doesn't persist between web requests

I've created a brand new ASP.Net 4.6 MVC project, and have tried to set a value in the Requests Cookies collection and retrieve it in the next request. I'm using cookies because Session isn't available yet within the Application_BeginRequest method. Using the following code, the cookie value I ask for is null in every request I make, despite setting it.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
protected void Application_BeginRequest()
{
var cookie = this.Request.Cookies.Get("Foo");
string value = cookie?.Value;
if (string.IsNullOrEmpty(value))
{
cookie = new HttpCookie("Foo", "Bar");
cookie.Expires = System.DateTime.UtcNow.AddHours(1);
this.Request.Cookies.Add(cookie);
}
}
protected void Application_EndRequest()
{
var cookie = this.Request.Cookies.Get("Foo");
string value = cookie?.Value;
}
}
What am I doing wrong? All of the posts I've seen relating to cookies shows setting/getting them in this fashion, with Request.Cookies.Get/Request.Cookies.Add.
You are not setting the cookie in this code you are only reading it, I made this same mistake. Use this
this.Response.Cookies.Add(cookie);
instead of
this.Request.Cookies.Add(cookie);
You should now see it in google chromes Application -> Cookies for your site
If you want to get state for each request, you have to do in Application_AcquireRequestState
Your Application_AcquireRequestState implementation should be :
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
var cookie = this.Request.Cookies.Get("Foo");
string value = cookie?.Value;
if (string.IsNullOrEmpty(value))
{
cookie = new HttpCookie("Foo", "Bar");
cookie.Expires = System.DateTime.UtcNow.AddHours(1);
this.Request.Cookies.Add(cookie);
}
}

Passing parameters to remote SSRS report from ASP.NET MVC application

I have an ASP.NET MVC application that uses SSRS for reporting (using a web form and report viewer). I would like to pass two parameters dynamically to the remote report. My current implementation stores the parameters in session, which works fine on VS Development Server, but the variable is null on IIS, upon retrieval in the web form.
Here is the controller method that calls the view
public ActionResult ShowReport(string id)
{
var reportParameters = new Dictionary<string, string>();
reportParameters.Add("Param1", id);
reportParameters.Add("Param2", "user1");
Session["reportParameters"] = reportParameters;
return View("ReportName");
}
And here is how I attempt to retrieve the parameters from the web form
protected void Page_Load(object sender, EventArgs e)
{
var reportParameters = (Dictionary<string, string>)Session["reportParameters"];
foreach (var item in reportParameters)
{
ReportParameter rp = new ReportParameter(item.Key, item.Value);
ReportViewer1.ServerReport.SetParameters(rp);
}
}
Anyone know why Session["reportParameters"] is null?
Or is there some other way of passing these parameters?
You can do it too:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
var js = new JavaScriptSerializer();
string reportPath= Request.QueryString["LocalReport"];
string parametersTemp = Request.QueryString["ParametersReport"];
List<ReportParameter> parameters = null;
if (parametrosTemp != "")
{
parameters = JsonConvert.DeserializeObject
<List<ReportParameter>>(parametrosTemp);
}
GenerateReport(reportPath, parameters );
}
catch (Exception ex) {
statusReport.Value = ex.Message;
}
}
}
private void GenerateReport(string reportPath, List<ReportParameter> reportParameters)
{
reportCurrent.ProcessingMode = ProcessingMode.Remote;
ServerReport serverReport = reportCurrent.ServerReport;
serverReport.ReportServerUrl =
new Uri(AppSettings.URLReportServer);
serverReport.ReportPath = reportPath;
serverReport.Refresh();
if (reportParameters != null)
{
reportCurrent.ServerReport.SetParameters(reportParameters);
}
}
Is the problem that Session["reportParameters"] is null or is it that you don't get any parameters added to your report? Because your code, as it stands, won't add parameters to your report even if you pass them across properly and so the report parameters will be null.
SetParameters takes IEnumerable<ReportParameter> (usually a List), not a ReportParameterobject. Your code should look more like this:
protected void Page_Load(object sender, EventArgs e)
{
var reportParameters = (Dictionary<string, string>)Session["reportParameters"];
List<ReportParameter> parameters = new List<ReportParameter>();
foreach (var item in reportParameters)
{
parameters.Add(new ReportParameter(item.Key, item.Value););
}
ReportViewer1.ServerReport.SetParameters(parameters);
}

Using session for user authentication in asp.net c#

I am using session to authenticate a user. I have 2 web pages in my project. One is webform and other one is EntryForm.aspx and other one is log.aspx
In log.aspx i have done
protected void Button1_Click(object sender, EventArgs e)
{
user_login loginu = new user_login();
String uid_db = loginu.login(this.DropDownList1, this.TextBox1, this.TextBox2, this.Label5);
if (uid_db == "invalid")
{
Label5.Visible = true;
Label5.Text = "Invalid Login";
}
else
{
string uname = uid_db.Substring(0, uid_db.IndexOf(",")).Trim();
string[] tokens = uid_db.Split(',');
string dbname = tokens[tokens.Length - 1];
Session["login"] = uname;
Session["db"] = dbname;
Response.Redirect("EntryForm.aspx");
}
}
In class user_login I am taking the password stored in the database and matching it with the value entered by user. if it finds a value i redirect it to EntryForm.aspx. In which i check for session variable as follows
protected void Page_Load(object sender, EventArgs e)
{// CHEK SESSION VARIABLE AND LOAD dropdownlist1 WITH VALUES
if (!IsPostBack)
{
String DB = "";
String AccountID = "";
if (Session["login"] != null && Session["db"] != null)
{
AccountID = Session["login"].ToString();
DB = Session["db"].ToString();
Label9.Text = AccountID;
}
else
{
Response.Redirect("log.aspx");
}
HiddenField1.Value = DB.ToString();
DropDown a = new DropDown();
a.filldropdown1(this.DropDownList1, DB);
}
}
This is what i have done do authenticate a user. On server i have done the following configuration:
I have done no settings in Global.asax nor anything is web.config . I have seen many forum wherein Global.asax and web.config is configured.
I want to know what do i need to do in my project in order to be very efficient to work. I am facing problem with session timeout. I have set it to 20 mins on my server but sometimes suddenly i get logged out.
Please help me to understand using session for authentication.
First of all you have to edit web.config and set session timeout attribute.
<configuration>
<system.web>
<sessionState timeout="200"></sessionState>
</system.web>
</configuration>
Another issue is the use of IsPostBack block.
protected void Page_Load(object sender, EventArgs e)
{
if (Session["login"] != null && Session["db"] != null)
{
String DB = "";
String AccountID = "";
AccountID = Session["login"].ToString();
DB = Session["db"].ToString();
Label9.Text = AccountID;
HiddenField1.Value = DB.ToString();
DropDown a = new DropDown();
a.filldropdown1(this.DropDownList1, DB);
}
else
{
Response.Redirect("log.aspx");
}
}

IsAuthenticated is false! weird behaviour + review question

This is the login function (after I validate user name and password, I load user data into "user" variable and call Login function:
public static void Login(IUser user)
{
HttpResponse Response = HttpContext.Current.Response;
HttpRequest Request = HttpContext.Current.Request;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
user.UserId.ToString(), DateTime.Now, DateTime.Now.AddHours(12), false,
UserResolver.Serialize(user));
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(ticket));
cookie.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(cookie);
string redirectUrl = user.HomePage;
Response.Redirect(redirectUrl, true);
}
UserResolver is the following class:
public class UserResolver
{
public static IUser Current
{
get
{
IUser user = null;
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
user = Desrialize(ticket.UserData);
}
return user;
}
}
public static string Serialize(IUser user)
{
StringBuilder data = new StringBuilder();
StringWriter w = new StringWriter(data);
string type = user.GetType().ToString();
//w.Write(type.Length);
w.WriteLine(user.GetType().ToString());
StringBuilder userData = new StringBuilder();
XmlSerializer serializer = new XmlSerializer(user.GetType());
serializer.Serialize(new StringWriter(userData), user);
w.Write(userData.ToString());
w.Close();
return data.ToString();
}
public static IUser Desrialize(string data)
{
StringReader r = new StringReader(data);
string typeStr = r.ReadLine();
Type type=Type.GetType(typeStr);
string userData = r.ReadToEnd();
XmlSerializer serializer = new XmlSerializer(type);
return (IUser)serializer.Deserialize(new StringReader(userData));
}
}
And the global.asax implements the following:
void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
IPrincipal p = HttpContext.Current.User;
if (p.Identity.IsAuthenticated)
{
IUser user = UserResolver.Current;
Role[] roles = user.GetUserRoles();
HttpContext.Current.User = Thread.CurrentPrincipal =
new GenericPrincipal(p.Identity, Role.ToString(roles));
}
}
First question:
Am I do it right?
Second question - weird thing!
The user variable I pass to Login has 4 members: UserName, Password, Name, Id.
When UserResolver.Current executed, I got the user instance.
I descided to change the user structure - I add an array of Warehouse object.
Since that time, when UserResolver.Current executed (after Login), HttpContext.Current.User.Identity.IsAuthenticated was false and I couldn't get the user data.
When I removed the Warehouse[] from user structure, it starts to be ok again and HttpContext.Current.User.Identity.IsAuthenticated become true after I Login.
What is the reason to this weird behaviour?
First, you don't need to do an HttpContext.Current from Global.asax. Global.asax derives from HttpApplication. So all you need to do is to get the Context property. This might help make that code a little cleaner.
//this is all you need in your global.asax
void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if(Context.User.Identity.IsAuthenticated)
{
var user = UserResolver.Current;
Context.User = Thread.CurrentPrincipal = new UserWrapperPrincipal(user, Context.User.Identity);
}
}
//this helper class separates the complexity
public class UserWrapperPrincipal: IPrincipal, IUser
{
private readonly IUser _user;
private readonly IIdentity _identity;
public UserWrapperPrincipal(IUser user, IIdentity identity)
{
_user = user;
_identity = identity;
}
private IList<string> RoleNames
{
get { return _user.GetUserRoles().Select(role => role.ToString()); }
}
public IIdentity Identity { get { return _identity; } }
public bool IsInRole(string role) { return RoleNames.Contains(role); }
}
Based on your error, it seems like the issue is that either your serializing function or your deserializing function corrupts the data. However, the problem area is probably not those functions. Either there is an issue in serializing the Warehouse object (serializing complex types can sometimes be tricky), or in the serialization of the actual array. Since you are using the default .NET XmlSerializer, There is a good article on customizing and controlling the way different objects are handled available at http://www.diranieh.com/NETSerialization/XMLSerialization.htm .
On another note, are you sure that this is the best way for you to store this data in your application? Storing a user-id and name makes sense. When you start storing serialized arrays of complex objects in your cookie, it might indicate you are not approaching the problem correctly to begin with.
I am guessing that your code is in a log on event somewhere and your building a custom forms auth.
You also need to then build the User object from the cookie on every page request
public class AuthHttpModule : IHttpModule {
public virtual void Init(HttpApplication app) {
app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest);
}
private void app_AuthenticateRequest(object source, EventArgs e) {
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) {
HttpContext.Current.User = null;
} else {
cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]);
}
bool result = HttpContext.Current.Request.IsAuthenticated;
}
}
EDIT
Try adding this to your global
void Application_AuthenticateRequest(Object sender, EventArgs e)
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null) {
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]);
}
}

How to log POSTed forms submissions?

Back in the ASP classic days when i needed to write out the name/value pairs of forms submitted by POST i thru this loop into the page:
on error resume next
for each x in Request.Form
Response.AppendToLog x & "=" & Request(x)
next
It threw all the form fields and values into the log just as GETs are. Does IIS7 .net give me any better method? (this is for the dev/testing portion of the project i don't have any concern about the space or cycles used to accomplish this).
thx
You can create an http module to log all posts. It allows you to log outside of the pages, a single point of logging instead of having to add the logic to all pages where you want to log activity.
Here you have some of the code. You would have to avoid logging viewstate since is tons of useless information. So you have to add some logic to achieve this.
public class ActivityLogModule: IHttpModule
{
public void Init(HttpApplication application)
{
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if (RecordActivity(context))
{
ActivityLogger.Instance.Log(application.Context.User.Identity.Name,
application.Context.Request.Url.AbsoluteUri,
application.Context.Request.Form.ToString());
}
}
public void Dispose(){}
protected bool RecordActivity(HttpContext context)
{
if (!context.Request.RequestType.Equals("POST"))
{
return false;
}
return true;
}
}
You could have something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
LogPostValues();
}
private void LogPostValues()
{
string logPath = #"C:\PostedValuesLog.txt";
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Logging: {0}", Request.Path);
sb.Append("Form Values");
foreach (string key in Request.Form)
{
string val = Request.Form[key];
sb.AppendFormat("{0} = {1}<br/>", key, val);
}
sb.Append(Environment.NewLine);
sb.Append("QueryString Values");
foreach (string key in Request.QueryString)
{
string val = Request.QueryString[key];
sb.AppendFormat("{0} = {1}<br/>", key, val);
}
sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine);
File.AppendAllText(logPath, sb.ToString());
}
This is a crude method though and shouldn't really be used in production code. However, as this is just for development & testing, it should suffice to track what data is being posted to your page via the querystring and form.

Resources