Feature Event has 'null' objects - sharepoint

public class Feature1EventReceiver : SPFeatureReceiver
{
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
string sContextNull = (SPContext.Current == null) ? "Context is NULL" : "Context is OK";
string sFeatureNull = (properties.Feature == null) ? "Feature is NULL" : "Feature is OK";
// Some code here
...
...
{
}
The feature has successfully installed (without error in logs). My problem is that sContextNull always returns "Context is NULL". And sFeatureNull always returns "Feature is NULL" too. Is there a way to get not null values of SPContext.Current and properties.Feature?
Another method FeatureActivated returns Context is NULL and Feature is OK. WTF?

SPContext.Current
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spcontext.current.aspx
Gets the context of the current HTTP request in Microsoft SharePoint Foundation.
SPFeatureReceiver.FeatureInstalled is executing when a feature is installed into a farm, which is done with a deploy/install command from stsadm or powershell, which then usually triggers the timer job to do the work. At this point there is no HTTP request, so SPContext.Current returns null.

Probably properties.Feature in method FeatureInstalled is a bug. I have tried the next code and it works for me:
public class Feature1EventReceiver : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
string sFeatureNull = (properties.Feature == null) ? "Feature is NULL" : "Feature is OK";
// Some code here
...
...
{
}
this method return Feature is OK.
Please avoid using properties.Feature in the method FeatureInstalled and FeatureUninstalling!!!

I think you need to get the web which contains this feature so try to use
(properties.Feature.Parent as SPWeb)
It works fine with me
Note:Try to cast it to SPSite if the feature scope is site

Related

Authenticate Attribute for MVC: ExecuteServiceStackFiltersAttribute: SessionFeature not present in time to set AuthSession?

I'm trying to create a simple Credentials Auth using OrmLiteAuthRepository(Postgres) and Memcached as caching layer on Mono 3.2.x / Ubuntu 12.04 in an MVC Application - I am using ServiceStack libraries version 4.0x
I am using a custom session object, adapted from ServiceStack's SocialBootstrap example
What works perfectly:
Getting the session inside a controller action, such as:
var currentSession = base.SessionAs<MyCustomUserSession>();
However, I don't want to check / validate the session and what may or may not be inside it in the action code, I would like to use an attribute, and this leads me to:
What does not work: Using the Authenticate attribute above the action name:
My problem (null AuthSession) shows up when trying to utilize the [Authenticate] attribute on an MVC action.
[Authenticate]
public ActionResult Index()
{
return View();
}
I have managed to narrow it down to the fact that ExecuteServiceStackFiltersAttribute executes this code, but it appears the AuthSession has not yet been made available by the SessionFeature - so the AuthSession will always be null at this point:
var authAttrs = GetActionAndControllerAttributes<AuthenticateAttribute>(filterContext);
if (authAttrs.Count > 0 && ( ssController.AuthSession==null || !ssController.AuthSession.IsAuthenticated))
{
filterContext.Result = ssController.AuthenticationErrorResult;
return;
}
If, for example I override the AuthenticationErrorResult and try to throw an exception if I manually initialize the session from the SessionFeature, it will throw the "there is life in the session" exception (of course, when I logged in with a valid user):
public override ActionResult AuthenticationErrorResult
{
get
{
if (AuthSession == null)
{
// the Authenticate filter is triggered by ExecuteServiceStackFilters attribute
// which seems to always have AuthSession null
var session = SessionFeature.GetOrCreateSession<MyCustomUserSession>(AuthService.Cache);
if (session == null || (session != null && session.IsAuthenticated == false))
{
throw new Exception("Hmmm...dead as a dodo");
}
else
{
throw new Exception("there is life in the session:" + session.UserName);
}
}
var returnUrl = HttpContext.Request.Url.PathAndQuery;
return new RedirectResult(LoginRedirectUrl.Fmt(HttpUtility.UrlEncode(returnUrl)));
}
}
Aside from creating my custom attributes / filters, is there a solution I should try (properties to set) with the incumbent ServiceStack codebase? If I'm missing something, please let me know.
My regards for a great project in any case.
My problem (null AuthSession) shows up when trying to utilize the [Authenticate] attribute on an MVC action.
Are you getting an Exception or are you just getting redirected to the 'Login' page? If you are not getting an Exception and just be redirected because you're not authenticated, the below may work. Also, are you implementing your own Custom Authentication Provider? If so, could you post a sample of it?
I don't think you have it in your code samples but I think your MVC Controller code is probably something like...
public class SomeController : ServiceStackController
{
[Authenticate]
public ActionResult Index()
{
return View();
}
}
Can you try adding your custom MyCustomUserSession to the Type of the ServiceStackController making it...
public class SomeController : ServiceStackController<MyCustomUserSession>
{
[Authenticate]
public ActionResult Index()
{
return View();
}
}

How to use ObjectContext.LoadProperty with EnablePlanCaching disabled?

On an ObjectContext object, I'm using code like this to load navigation properties.
context.LoadProperty(entity, navigationProperty,
System.Data.Objects.MergeOption.AppendOnly);
I would like to disable plan caching on queries that will be generated with this kind of call ?
Is it possible ?
Is there an alternative by wrapping the context with a DBContext ?
Thanks in advance.
I solved the problem by using a DBContext.
DbContext dbc = new DbContext(context, false);
dbc.Entry<T>(object).Reference<TReference>(#"ReferenceName").Query().DisablePlanCaching().Load();
dbc.Entry<T>(object).Collection<TCollection>(#"CollectionName").Query().DisablePlanCaching().Load();
with DisablePlanCaching extension method (inspired from the one found here) as :
public static IQueryable<T> DisablePlanCaching<T>(this IQueryable<T> query)
{
ObjectQuery<T> q = query as ObjectQuery<T>;
if ( q == null )
throw new InvalidOperationException(#"IQueryable<T> is not of type ObjectQuery<T>");
q.EnablePlanCaching = false;
return query;
}

Service Stack enable compression globally

WE used the following post to enable compression on our Service Stack API.
Enable gzip/deflate compression.
We have the following code in my AppHost file:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new ApiServiceRunner<TRequest>(this, actionContext);
}
And In my ApiServiceRunner I have the following:
public override object OnAfterExecute(IRequestContext requestContext, object response)
{
// if it's not null and not already compressed
if ((response != null) && !(response is CompressedResult))
// ToOptimizedResult already picks the most optimal compression (hence the name)
response = requestContext.ToOptimizedResult(response);
return base.OnAfterExecute(requestContext, response);
}
The problem is that this code now runs on EVERY response and we have one endpoint that just calls a json file from the server file system. When the code runs on this json file it totally kills the app pool on the server and I see a stack overflow exception when debugging an integration test that calls this json file.
So we have had to add in the following code into our AppHost file:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
bool useCustomRunner = actionContext.RequestType.Name != "HomepageLayoutConfigRequest";
return useCustomRunner
? new ApiServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
}
As you can see we don't use our custom ApiServiceRunner when the request type name is HomepageLayoutConfigRequest. This is ugly and we want a better way of doing this.
Any ideas?
thanks
RuSs
ps. here is my latest AppHost CreateServiceRunner override:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
var requestType = actionContext.RequestType;
string message = "The [EnableCompression] attribute exists: {0}";
Debug.WriteLine(string.Format("The requestType was {0}", requestType));
var useCustomRunner = requestType.HasAttribute<EnableCompression>();
Debug.WriteLine(string.Format(message, requestType.HasAttribute<EnableCompression>()));
#region for serviceType if we ever need it. Currently it doesnt work as the guys at SS say it should
// https://stackoverflow.com/questions/19127522/service-stack-enable-compression-globally
// Commented out at there is nothing in the EndpointHost.Metadata so getting a null exception - we only need to use the attribute on the request DTO anyway.
// #Mythz - the following code is the code that doesnt work as per my comments
//var serviceType = EndpointHost.Metadata.GetServiceTypeByRequest(requestType);
// #Mythz- this (serviceType) is always null. It is available in next iteration of debugging (1 iteration behind)
//if (serviceType != null && !useCustomRunner)
//{
// Debug.WriteLine(string.Format("The serviceType was {0}", serviceType));
// useCustomRunner = serviceType.HasAttribute<EnableCompression>();
// Debug.WriteLine(string.Format(message, serviceType.HasAttribute<EnableCompression>()));
//}
#endregion
return useCustomRunner
? new ApiServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
}
I think you're on the right track, tho I'd prefer to use a Custom Attribute instead, e.g to only enable compression for Service classes or Request DTO's which are marked with [EnableCompression], you can do:
var serviceType = actionContext.ServiceType;
var requestType = actionContext.RequestType;
var useCustomRunner = serviceType.HasAttribute<EnableCompressionAttribute>()
|| requestType.HasAttribute<EnableCompressionAttribute>()
return useCustomRunner
? new ApiServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
I personally like the declarative intent of [EnableCompression] but you can also use something like [UseCustomRunner] if your ApiServiceRunner ends up doing more than just compression.

Sharepoint Webpart custom properties get default values on server reboot

I have noticed that the custom properties of a webpart I developed return to their default values when I reboot my machine.
Is that a normal behavior? are the properties saved as far as the server is up, or there is some parameters I am missing.
Thank you.
EDIT: code:
namespace TestWebpart
{
[ToolboxItemAttribute(false)]
[XmlRoot(Namespace = "TestWebpart")]
public class GraphWebpart : Microsoft.SharePoint.WebPartPages.WebPart
{
// Visual Studio might automatically update this path when you change the Visual Web Part project item.
private const string _ascxPath = #"~/_CONTROLTEMPLATES/Test_Graph/TestWebpart/GraphWebpartUserControl.ascx";
protected override void CreateChildControls()
{
ReloadElements();
}
protected void ReloadElements()
{
Controls.Clear();
GraphWebpartUserControl control = (GraphWebpartUserControl)Page.LoadControl(_ascxPath);
control.xmlDataUrl = XMLFileUrl;
Controls.Add(control);
}
private static string _xmlFileUrl;
[WebBrowsable(true),
Personalizable(PersonalizationScope.Shared),
DefaultValue(""),
Description("xml"),
DisplayName("xml"),
WebDisplayName("xml")]
public string XMLFileUrl
{
get { return _xmlFileUrl; }
set {
_xmlFileUrl = value;
ReloadElements();
}
}
}
}
EDIT2:
Deleting static from the fields throws the flowing exception:
Web Part Error: An error occurred while setting the value of this property: TestWebpart:XMLFileUrl - Exception has been thrown by the target of an invocation.
Hide Error Details
[WebPartPageUserException: An error occurred while setting the value of this property: Blue_Graph.GraphWebpart.GraphWebpart:XMLFileUrl - Exception has been thrown by the target of an invocation.]
at Microsoft.SharePoint.WebPartPages.BinaryWebPartDeserializer.ApplyPropertyState(Control control)
at Microsoft.SharePoint.WebPartPages.BinaryWebPartDeserializer.Deserialize()
at Microsoft.SharePoint.WebPartPages.SPWebPartManager.CreateWebPartsFromRowSetData(Boolean onlyInitializeClosedWebParts)
First of all you should not have
private static string _xmlFileUrl;
it should be
private string _xmlFileUrl;
This static variable will be lost on IISRESET - won't work in a farm and has the potential to cause all sort of 'thread safe' issues if used multi-threaded environment (like a web server) so only use them if they are really needed.
When SharePoint loads a web part (or after you click Save/Apply in the toolpart) it uses reflection to find your properties (the [Browsable... attribute) and then serialization to load/save the value of the property to the database. One of these two is failing.
I would suspect that is some problem with the attribute - try this one and work backwards until it stops working ;)
[Browsable(true),
Category("Miscellaneous"),
DefaultValue(defaultText),
WebPartStorage(Storage.Personal),
FriendlyName("Text"),
Description("Text Property")]

SPWorkflowActivationProperties.Item is NULL in Simple SharePoint Workflow

I have generated a C# SharePoint Sequential Workflow project using the very handy STSDEV tool (it got me around the requirement to have access to a 32-bit SharePoint installation which is required for other tools such as VSeWSS 1.3).
I've added a simple 'modify the title' action to test my basic setup:
public sealed partial class CopyWorkflow : SharePointSequentialWorkflowActivity
{
public CopyWorkflow()
{
InitializeComponent();
workflowProperties = new SPWorkflowActivationProperties();
}
public SPWorkflowActivationProperties workflowProperties;
private void onWorkflowActivated1_Invoked_1(object sender, ExternalDataEventArgs e)
{
workflowProperties.Item["Title"] = workflowProperties.Item["Title"].ToString() + ": Processed by Workflow";
workflowProperties.Item.Update();
}
}
Whoever, after installing my workflow via WSP into an installation of WSS 3.0, activating the feature, and configuring the workflow to start whenever a new item is created for a particular list, I get my breakpoint in onWorkflowActivated1_Invoked_1 hit, but the workflowProperties.Item is always NULL instead of an SPListItem representing the item that was just added.
What do I need to do to get the Item to be filled when this callback is called?
Update: I've noticed that the thread executing the workflow is running anonymously rather than as the logged in user or the system user, and therefore won't have access to the list data. Furthermore, the SharePoint log file show the following exception:
Unexpected System.ArgumentNullException: Value cannot be null. Parameter name: uriString at System.Uri..ctor(String uriString) at Microsoft.SharePoint.SPSite..ctor(String requestUrl) at Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties.<get_Site>b__0() at Microsoft.SharePoint.SPSecurity.CodeToRunElevatedWrapper(Object state) at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass4.<RunWithElevatedPrivileges>b__2() at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode) at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param) at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode) at Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties....
and
Unexpected ...get_Site() at Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties.get_Web() at Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties.get_Item() at BechtelWorkflow.CopyWorkflow.onWorkflowActivated1_Invoked_1(Object sender, ExternalDataEventArgs e) at System.Workflow.ComponentModel.Activity.RaiseGenericEvent[T](DependencyProperty dependencyEvent, Object sender, T e) at System.Workflow.Activities.HandleExternalEventActivity.RaiseEvent(Object[] args) at System.Workflow.Activities.HandleExternalEventActivity.Execute(ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor'1.Execute(T activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor'1.Execute(Activity activi...
Have you bound WorkflowActivationProperties with Workflow designer?
WorkflowActivationProperties http://img718.imageshack.us/img718/9703/ss20100305091353.png
This issue occurs if the the InitialStateName of the designer in the workflow properties is not equal to "Initial state" or is pointed to other stage abruptly.
Once a state wherein we have the workflowProperties ,etc like the above image. Things start working as required.

Resources