Is is possible to retrieve a Session variable from a different controller it was created from?
I create this in my Account controller
System.Web.HttpContext.Current.Session["Session"] = sessionGuid;
and from a different controller I'm trying
if (System.Web.HttpContext.Current.Session["Session"] != null)
{
return Json(System.Web.HttpContext.Current.Session["Session"].ToString());
}
return null;
which always returns null.
as a Test I added some code to my Login controller and in that part i do get the value out of it
if (System.Web.HttpContext.Current.Session["Session"] != null)
{
test = System.Web.HttpContext.Current.Session["Session"].ToString();
}
else
{
test = "no";
}
i always got the actual result, not the"no" part of the code
For some reason its different into how i have to access the session, at the other controller i changed to this code and it worked
if (HttpContext.Session["Session"] != null)
{
return Json(HttpContext.Session["Session"].ToString());
}
return null;
if controller is within the same website/virtual directory then YES, however if you are saying your session was created in a different site and you trying to access it within a controller which belongs to different site then you cannot.
Related
I've got a controller action that is using TempData to get complex objects from another action. The issue happens when the user refreshes the page and gets null object errors on the view. The complex objects are not passed through the URL like the other values are. Is there a way to prevent this from happening? An alternative solution would be to remove all query parameters from the URL on a page refresh and display the view like it was a new object.
Controller
public IActionResult Daily(Daily daily)
{
new ReportDaily().GetAvailableSavedCriteria(out List<ReportCriteria> reportCriteria, out Notification not);
if (daily.SelectedCriteria == null) {
//Create daily report object and initialize the default values
var newModel = new Daily
{
PaymentTypes = DGetPaymentTypes(),
Users = DGetUsers(),
Criteria = reportCriteria,
StartDate = DateTime.Today.Date,
EndDate = DateTime.Today.Date,
County = true,
Municipality = true
};
return View(newModel);
}
else
{
daily.PaymentTypes = TempData.Get<List<Daily.PaymentType>>("PaymentTypes") == null ? DGetPaymentTypes() : TempData.Get<List<Daily.PaymentType>>("PaymentTypes");
daily.Users = TempData.Get<List<Daily.User>>("Users") == null ? DGetUsers() : TempData.Get<List<Daily.User>>("Users");
daily.Criteria = reportCriteria;
return View("Daily", daily);
}
}
TempData only used for a single redirect, to keep the data from another action after refreshing, you can use Session to achieve it.
To use Session in core mvc, you need to add following codes to the starup.cs fileļ¼
Add services.AddSession(); in ConfigureServices method.
Add app.UseSession(); in Configure method.
To save complex object in Session,you can convert the list object into a json format for storage, and then deserialize it into a list object when you get it.
HttpContext.Session.SetString("PaymentTypes", JsonConvert.SerializeObject(pamentTypeList));
Daily Action:
//.....
daily.PaymentTypes = HttpContext.Session.GetString("PaymentTypes") == null ? DGetPaymentTypes() : JsonConvert.DeserializeObject<List<Daily.PaymentType>> (HttpContext.Session.GetString("PaymentTypes"));
The following two links access the same action method:
http://stage.bullydog.com/Products/accessories/podmount and http://stage.sctflash.com/Products/accessories/podmount
I use Request.Url.Host to determine the brand of products I want to return from a database. When I access http://stage.bullydog.com/Products/accessories/podmount first, Request.Url.Host contains the value stage.bullydog.com, but if I then go to http://stage.sctflash.com/Products/accessories/podmount, Request.Url.Host may contain stage.sctflash.com or it may contain stage.bullydog.com.
The action method that is called is:
public ActionResult GetAccessoriesByType(RenderModel model, string id)
{
Common _common = new Common();
string brand = Request.Url != null ? _common.GetProductBrand() : BrandType.SCT;
var productSearchResultsModel = new ProductSearchResultsModel
{
Accessories = _accessoryRepository.GetAccessoriesByType(id, brand)
};
return View("~/Views/accessories.cshtml", productSearchResultsModel);
}
The code that gets the brand is:
public class Common
{
public string GetProductBrand()
{
var host = HttpContext.Current.Request.Url.Host;
if (host.Contains("sctflash"))
return BrandType.SCT;
if (host.Contains("bigrig") || host.Contains("bigrigs"))
return BrandType.BigRig;
if (host.Contains("bullydog"))
return BrandType.BullyDog;
return BrandType.SCT;
}
}
How can I ensure the Request.Url.Host contains the proper host when the same action method is accessed from two different hosts?
You can see this in action if you go to http://stage.bullydog.com/Products/accessories/podmount and then go to http://stage.sctflash.com/Products/accessories/podmount and refresh either one, the logo should change which means that the value returned by Request.Url.Host was incorrect.
Also, can GetProductBrand be static and still be thread-safe in this case?
The reason why accessing another website was bringing back the one websites content and the Request.Url.Host had the other websites information was because I had declared OutPutCache[Duration=60] at the top of my controller. If I waited 60 seconds and then refreshed, the correct data for each website would return. Once I removed this from the controller, everything worked as expected.
I created session to move data between pages using c# asp.net but the result does not appear and the program does not give me error in the code
first page code:
Session["New1"] = desc1.Text;
to send data to Label in Second page
code:
var userType = (string)Session["New1"];
if (userType != null)
{
Label1.Text = userType.ToString() ;
}
else
{
// test "2" etc
}
Try this,
if (Session["New1"]!= null)
{
Label1.Text = Session["New1"].ToString() ;
}
else
{
// test "2" etc
}
Try explicitly checking of your Session variable exists before attempting to use it to avoid any null-reference issues :
// Explicitly check that it exists
if (Session["New1"] != null)
{
// Then grab it (if it is a non-string type, then you can use as to cast it
// (e.g. a List might use Session["List"] as List<Widget>;)
Label1.Text = Convert.ToString(Session["New1"]);
}
else
{
// Do something here
}
This assumes that your value will be set prior to this code getting called. Additionally, any hiccups to the web server (e.g. timeouts, restarts, major exceptions, etc.) will clear all of the values within the Session.
I have a several methods in controller:
public ActionResult Issue()
{
var message = WSFederationMessage.CreateFromUri(HttpContext.Request.Url);
// sign in
var signinMessage = message as SignInRequestMessage;
if (signinMessage != null)
{
return ProcessWSFederationSignIn(signinMessage, ClaimsPrincipal.Current);
}
// sign out
var signoutMessage = message as SignOutRequestMessage;
if (signoutMessage != null)
{
return ProcessWSFederationSignOut(signoutMessage);
}
return View("Error");
}
And the most valuable for me in this question:
private ActionResult ProcessWSFederationSignOut(SignOutRequestMessage message)
{
FederatedAuthentication.SessionAuthenticationModule.SignOut();
var mgr = new SignInSessionsManager(HttpContext, _cookieName);
// check for return url
if (!string.IsNullOrWhiteSpace(message.Reply) && mgr.ContainsUrl(message.Reply))
{
ViewBag.ReturnUrl = message.Reply;
}
return View("Signout");
}
All works fine, but, there are interesting moment.
This thing works in both cases, if I ended session by myself, or session simply expired. Its fine but actually, I need to tell the difference between those cases, write in ViewBag something like "You are singed out" or "Session expired" depends on result and show it oy the View.
Is there are some kind of way to detect session expired situations or should it be something different?
P.S Sorry for my bad English.
Since you changed the topic I will update my answer. I haven't used WSFederatinSession but maybe you could store the inf about how session ended (in a cookie for example) and during the next request (in a global asax for example) read this inf and do what you want to do.
I'm building a small application in MVC 4.5. I've got an Azure database, and i'm using code first with the Entity framework to set it up. The app is hosted on my development sharepoint area.
The Home controller's Index() Action has the [SharePointContextFilter] and loads, among other things, the username of the logged in user. When the application is debugged and this first action runs, the Sharepoint {StandardTokens} get appended to the url, so SPHostUrl and AppWebUrl and a few other variables get added to the query string.
If i navigate away to an action without the [SharePointContextFilter] it works fine, until i navigate back to the action with the [SharePointContextFilter]. Then i get an error saying:
Unknown User
Unable to determine your identity. Please try again by launching the app installed on your site.
I assume this is because a few of the Sharepoint {StandardTokens} are missing, because if i manually append them to the link like so:
#Url.Action("Index", "Home", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Current.Request).AbsoluteUri })
and mark the other action with the [SharePointContextFilter] as well, it still works.
Hovever this seems like a needlessly complex way to solve this problem. I don't want to mark every single action in my app with the [SharePointContextFilter], and manually insert the {StandardTokens} into the query string for every link i create. Shouldn't it be possible to save this information to session or a cookie in some way, so i don't have to do this?
For reference, here is some code:
HomeController.Index(), the first Action that is run.
[SharePointContextFilter]
public ActionResult Index()
{
User spUser = null;
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
spUser = clientContext.Web.CurrentUser;
clientContext.Load(spUser, user => user.Title);
clientContext.ExecuteQuery();
ViewBag.UserName = spUser.Title;
}
}
return View();
}
Here is the [SharePointContextFilter] attribute (generated by visual studio):
/// <summary>
/// SharePoint action filter attribute.
/// </summary>
public class SharePointContextFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
SharePointContext currentContext = SharePointContextProvider.Current.GetSharePointContext(filterContext.HttpContext);
Uri redirectUrl;
switch (SharePointContextProvider.CheckRedirectionStatus(filterContext.HttpContext, out redirectUrl))
{
case RedirectionStatus.Ok:
return;
case RedirectionStatus.ShouldRedirect:
filterContext.Result = new RedirectResult(redirectUrl.AbsoluteUri);
break;
case RedirectionStatus.CanNotRedirect:
filterContext.Result = new ViewResult { ViewName = "Error" };
break;
}
}
}
The links that i use. From the _Layout.cshtml file.:
<li id="Home">Home</li>
<li id="Contract">Avrop</li>
If i try to use these links from an Action that isn't marked with the [SharePointContextFilter] filter, the SPHostUrl isn't found. If i try to link to an Action which is marked with the [SharePointContextFilter] filter, i get the aforementioned error if the SPHostUrl isn't included.
This basically creates a situation where i can navigate away from the filtered actions, but then i can never return to them.
I hope this was clear enough.
We had the same problem - ASP.NET MVC 4.5. There are two things that worked for us:
1) There is a spcontext.js file (included in the solution - you just have to add a reference to it) that will automatically append the tokens to the URL for you. However, we were given a requirement that the URL must look "nice," so we went with option 2..
2) Put the context in the session. Have the filter first look to see if you have the context in your session, and if it's there, then use that. If not, try the query string and put the retrieved context in your session. This means that you originally have to access your site with the tokens attached to your url string, and it also means that your context will be in the session for however long that's alive - so you have to decide if that's ok.
Another option would be to comment out the validation of the SPHostUrl in the SharePointContext class at the two places shown below. It works fine without it and voids the need for passing around QueryString parameters as it will just pull it from the Session state.
Location 1 is in public SharePointContext GetSharePointContext(HttpContextBase httpContext):
/// <summary>
/// Gets a SharePointContext instance associated with the specified HTTP context.
/// </summary>
/// <param name="httpContext">The HTTP context.</param>
/// <returns>The SharePointContext instance. Returns <c>null</c> if not found and a new instance can't be created.</returns>
public SharePointContext GetSharePointContext(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
// Commented out to allow it to work without the SPHostUrl being passed around
//Uri spHostUrl = SharePointContext.GetSPHostUrl(httpContext.Request);
//if (spHostUrl == null)
//{
// return null;
//}
SharePointContext spContext = LoadSharePointContext(httpContext);
if (spContext == null || !ValidateSharePointContext(spContext, httpContext))
{
spContext = CreateSharePointContext(httpContext.Request);
if (spContext != null)
{
SaveSharePointContext(spContext, httpContext);
}
}
return spContext;
}
Location 2 is in protected override bool ValidateSharePointContext(SharePointContext spContext, HttpContextBase httpContext):
protected override bool ValidateSharePointContext(SharePointContext spContext, HttpContextBase httpContext)
{
SharePointAcsContext spAcsContext = spContext as SharePointAcsContext;
if (spAcsContext != null)
{
// Commented out to allow it to work without the SPHostUrl being passed around
//Uri spHostUrl = SharePointContext.GetSPHostUrl(httpContext.Request);
string contextToken = TokenHelper.GetContextTokenFromRequest(httpContext.Request);
HttpCookie spCacheKeyCookie = httpContext.Request.Cookies[SPCacheKeyKey];
string spCacheKey = spCacheKeyCookie != null ? spCacheKeyCookie.Value : null;
// Commented out to allow it to work without the SPHostUrl being passed around
//return spHostUrl == spAcsContext.SPHostUrl &&
return !string.IsNullOrEmpty(spAcsContext.CacheKey) &&
spCacheKey == spAcsContext.CacheKey &&
!string.IsNullOrEmpty(spAcsContext.ContextToken) &&
(string.IsNullOrEmpty(contextToken) || contextToken == spAcsContext.ContextToken);
}
return false;
}
Make sure the landing page of your App which will receive the initial request with the SPAppToken variable in the HTTP Post calls SharePointContext so the session variable will be created. This can be done by adding the following attribute either above your MVC Controller class or above your MVC Action method:
[SharePointContextFilter]
Or instead calling the following line of code from the MVC Controller:
SharePointContextProvider.Current.GetSharePointContext(HttpContext);