Sharepoint 2010 Event receiver not firing for subsite - sharepoint-2010

I have an event receiver (WebAdding and WebProvisioned) which works just fine for sites created off the root of the site collection. However, subsites (for example, teamsites created within other areas) do not trigger the code at all.
Does anyone have any idea as to why?
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using System.Text;
namespace TestEventReceiver.EventReceiver1
{
/// <summary>
/// Web Events
/// </summary>
public class EventReceiver1 : SPWebEventReceiver
{
/// <summary>
/// A site is being provisioned.
/// </summary>
public override void WebAdding(SPWebEventProperties properties)
{
base.WebAdding(properties);
using (SPWeb web = properties.Web)
{
StringBuilder output = new StringBuilder();
output.AppendFormat("Web Adding");
output.AppendFormat("<br>Web title: {0}",web.Title);
SendMyEmail(web, "SendItToMe#MyTestAddress.com", "Web Adding", output.ToString());
}
}
/// <summary>
/// A site was provisioned.
/// </summary>
public override void WebProvisioned(SPWebEventProperties properties)
{
base.WebProvisioned(properties);
using (SPWeb web = properties.Web)
{
StringBuilder output = new StringBuilder();
output.AppendFormat("Web Provisioned");
output.AppendFormat("<br>Web title: {0}", web.Title);
SendMyEmail(web, "SendItToMe#MyTestAddress.com", "Web Provisioned", output.ToString());
}
}
private void SendMyEmail(SPWeb Web, String toAddress, String subject, String message)
{
bool appendHtmlTag = false;
bool htmlEncode = true;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPUtility.SendEmail(Web, appendHtmlTag, htmlEncode, toAddress, subject, message);
});
}
}
}
Thanks in advance,
Matt

I think you should not be using 'Using' .
The SPWeb object reference you get is from properties.Web which is being passed to the WebAdding method. You will run into issues because of this.

Have a look at how your event receiver is provisioned - it may be the scope needs to be changed to Site rather than Web. Perhaps you could post here so we can see.

On my site I had the same issue. Still figuring out the xml files, but in my Elements.xml file for the Receivers, each receiver had the same sequence number. Once I made them unique within the Elements.xml file, the WebProvisioned event started firing. Don't know if this is the same issue you were having.

This code is showing the WebAdding event and that event is occurring on the parent Web.
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spwebeventreceiver.webadding.aspx

Try to change scope of your receiver (in Elements.xml file add attribute ). Also, make sure that the feature of your Event receiver is activated in you site features in the subsite.

Related

gRPC doesn't seem to generate client side code needed for accessing service

I am exploring gRPC by downloading and following the PortfoliosSample from here.
The sample code are all working fine. When I tried to create my own simple service and client by following the sample, however, I noticed that the generated code on the client side doesn't include the class and functions needed for accessing the service.
In the PortfoliosSample, the client side code generated based on the portfolios.proto includes and class named PortfoliosClinet (in PortfoliosGrpc.cs)
public partial class PortfoliosClient : grpc::ClientBase<PortfoliosClient>
Various functions (such as Get, in the class) are available for client side program to use for invoking the service.
In my generated code, BrokerGrpc.cs, there is no "GroupClient" class or anything similar in it. As a result, my client side code cannot use the generated code to access the service. What am I missing?
Here is the TSAPIBroker.proto file defined on the server
syntax = "proto3";
option csharp_namespace = "Test.API.TSAPIBroker.Protos";
package TSAPIBroker;
message Group {
int32 id = 1;
string name = 2;
}
message Groups {
repeated Group group = 1;
}
message GetRequest {
int32 groupId = 1;
}
message GetResponse {
Group group = 1;
}
service GroupService
{
rpc Get(GetRequest) returns (GetResponse);
}
And here is the generated TSAPIBrokerGrpc.cs
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: TSAPIBroker.proto
// </auto-generated>
#pragma warning disable 0414, 1591
#region Designer generated code
using grpc = global::Grpc.Core;
namespace Test.API.TSAPIBroker.Protos {
public static partial class GroupService
{
static readonly string __ServiceName = "TSAPIBroker.GroupService";
static readonly grpc::Marshaller<global::Test.API.TSAPIBroker.Protos.GetRequest> __Marshaller_TSAPIBroker_GetRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Test.API.TSAPIBroker.Protos.GetRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Test.API.TSAPIBroker.Protos.GetResponse> __Marshaller_TSAPIBroker_GetResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Test.API.TSAPIBroker.Protos.GetResponse.Parser.ParseFrom);
static readonly grpc::Method<global::Test.API.TSAPIBroker.Protos.GetRequest, global::Test.API.TSAPIBroker.Protos.GetResponse> __Method_Get = new grpc::Method<global::Test.API.TSAPIBroker.Protos.GetRequest, global::Test.API.TSAPIBroker.Protos.GetResponse>(
grpc::MethodType.Unary,
__ServiceName,
"Get",
__Marshaller_TSAPIBroker_GetRequest,
__Marshaller_TSAPIBroker_GetResponse);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Test.API.TSAPIBroker.Protos.TSAPIBrokerReflection.Descriptor.Services[0]; }
}
/// <summary>Base class for server-side implementations of GroupService</summary>
[grpc::BindServiceMethod(typeof(GroupService), "BindService")]
public abstract partial class GroupServiceBase
{
public virtual global::System.Threading.Tasks.Task<global::Test.API.TSAPIBroker.Protos.GetResponse> Get(global::Test.API.TSAPIBroker.Protos.GetRequest request, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
}
/// <summary>Creates service definition that can be registered with a server</summary>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static grpc::ServerServiceDefinition BindService(GroupServiceBase serviceImpl)
{
return grpc::ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_Get, serviceImpl.Get).Build();
}
/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
/// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
/// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static void BindService(grpc::ServiceBinderBase serviceBinder, GroupServiceBase serviceImpl)
{
serviceBinder.AddMethod(__Method_Get, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::Test.API.TSAPIBroker.Protos.GetRequest, global::Test.API.TSAPIBroker.Protos.GetResponse>(serviceImpl.Get));
}
}
}
#endregion
Using the container image mcr.microsoft.com/dotnet/sdk:5.0, I'm able to use your proto to generate both files:
TSAPIBroker.cs
TSAPIBrokerGrpc.cs
Repro:
dotnet new console
dotnet add package Grpc --version 2.33.1
dotnet add package Grpc.Tools --version 2.33.1
dotnet add package Google.Api.CommonProtos --version 2.2.0
Reference your proto from ther project file and then build.
My generated *Grpc.cs contains GroupServiceClientclass.
NOTE the message Groups is defined but not used.

Remote Validation in Asp.Net Core Razor Pages

I’m developing a web application using Razor Pages and Code First.
I know that in ASP.NET MVC, you can use Remote above a property referring to an action in a controller that validates the data without the whole page being posted back. But it doesn’t seem to work in Razor Pages as there’s no Controller and Action in ASP.NET Core Razor Pages.
So, How can I get remote validation done in Razor Pages?
For anyone like me who finds this later and loses their mind trying to pass a property from their model onto the validation method, make the method signature look like so
public IActionResult IsCharacterNameAvailable([Bind(Prefix = "Character.Name")] string name)
Character is the model and Name is the property. Without adding the [Bind(Prefix = "")] before the parameter I was always receiving a null value. Hope this helps!
I added the following in my model class:
[Remote(action: "IsNationalIdValid",controller:"Validations")]
I created 'Controllers' folder in my Razor Pages project and added a controller(ValidationsController) with the following method:
public IActionResult IsNationalIdValid(string nationalId){}
However,when I tried to go to the page where this validation was supposed to work,I got the following exception:
No URL for remote validation could be found in asp.net core
Thanks to a reply to the same thread in Asp.Net forum,I figured out the answer:
All I needed to do was to add the following code in Startup.cs file of my Razor Pages project in order to configure the route.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Hope this answer will help someone else as well.
In the base class that RemoteAttribute derives from there's a protected GetUrl() method than can be overriden. Therefore I created my own MyRemoteAttribute class
public class MyRemoteAttribute : RemoteAttribute
{
/// <summary>
/// Initialise an instance of the <see cref="MyRemoteAttribute"/>
/// </summary>
/// <param name="handler">The name of the Razor Page Handler</param>
/// <param name="page">The Razor Page name</param>
public MyRemoteAttribute(string handler = null, string page = null)
{
Handler = handler;
Page = page;
}
/// <summary>
/// Gets/sets the url to use for remote validation
/// </summary>
public string Url { get; set; }
public string Page { get; private set; }
public string Handler { get; private set; }
protected override string GetUrl(ClientModelValidationContext context)
{
// Use an URL is specified
if (!string.IsNullOrEmpty(Url)) return Url;
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(Handler))
{
throw new InvalidOperationException("No Handler specified");
}
var services = context.ActionContext.HttpContext.RequestServices;
var factory = services.GetRequiredService<Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory>();
var urlHelper = factory.GetUrlHelper(context.ActionContext);
var page = Page?? context.ActionContext.RouteData.Values["page"] as string;
Url = urlHelper.Page(page, Handler);
if (Url == null)
{
throw new InvalidOperationException();
}
return Url;
}
}
In my app which is using areas, creates a url /BusinessPartners/Clients/Create?handler=CheckUnique
To use decorate your model property with [MyRemote(Url="/Something/Somecheck")] to use the specified URL, or [MyRemote("CheckUnique")] to specify the Razor Page Handler. The handler should be named OnGet<handlername> and needs to return a JsonResult with true for passing validation, false or null if validation fails.
The handler in the Razor Page is:
public IActionResult OnGetCheckUnique(string shortName)
{
var found = db.Queryable<BusinessPartner>().Any(a => a.ShortName == shortName);
return new JsonResult(!found);
}
This is the same as you would do for the RemoteAttribute with the exception on the slightly modified naming convention.
I like my validation to be close to the point where it is used so therefore I've put it in the same page. I also have use a single [BindProperty] for a model class just to keep things neat and manageable.
Looks like there is a feature request for remote validation in ASP.NET Core Razor Pages but it is not priority:
https://github.com/aspnet/Mvc/issues/8245
The PageRemoteValidation attribute was introduced in ASP.NET Core 3.0 and is designed specifically to work with a Razor Pages handler method.
So, if you are working with ASP.NET Core 2.x, or your validation endpoint is an MVC controller, you must use the RemoteValidation attribute. If you are working with ASP.NET Core 3.x or newer, AND your validation service is a Razor Pages handler method, you must use the PageRemoteValidation attribute.
Here is an example describing this in details:

MVC 4.0 - sign in using Google

I know there's a lot of information about this subject, but I just can't seem to find an answer suitable to my specific needs:
I opened a new MVC 4.0 basic application (meaning, no "AuthConfig.cs" file exist).
I have already successfully implemented Facebook sign-in.
I can't seem to find any way to do the same with Google.
I already have a custom "Connect with google" button. I need a very simple code to authenticate using google. Please bare in mind, that after authentication, I need to get user information, and also get a hold of the user's calendar.
Please help
Thank you.
Some Code to help you get started
In AuthConfig file
OAuthWebSecurity.RegisterClient(new Mvc.GoogleCustomClient(), "Google", null);
In GoogleCustomClient.cs
public class GoogleCustomClient : OpenIdClient
{
public GoogleCustomClient()
: base("google", WellKnownProviders.Google) { }
/// <summary>
/// Gets the extra data obtained from the response message when authentication is successful.
/// </summary>
/// <param name="response">
/// The response message.
/// </param>
/// <returns>A dictionary of profile data; or null if no data is available.</returns>
protected override Dictionary<string, string> GetExtraData(IAuthenticationResponse response)
{
FetchResponse fetchResponse = response.GetExtension<FetchResponse>();
if (fetchResponse != null)
{
var extraData = new Dictionary<string, string>();
extraData.Add("email", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email));
extraData.Add("country", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.HomeAddress.Country));
extraData.Add("firstName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.First));
extraData.Add("lastName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.Last));
return extraData;
}
return null;
}
/// <summary>
/// Called just before the authentication request is sent to service provider.
/// </summary>
/// <param name="request">
/// The request.
/// </param>
protected override void OnBeforeSendingAuthenticationRequest(IAuthenticationRequest request)
{
// Attribute Exchange extensions
var fetchRequest = new FetchRequest();
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.HomeAddress.Country);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Name.First);
fetchRequest.Attributes.AddRequired(WellKnownAttributes.Name.Last);
request.AddExtension(fetchRequest);
}
}
You can Use this Code to retrieve the User Information from google.

AutoStart/Pre-warm features not working in IIS 7.5 / WCF service

For testing the many headaches of IIS/WCF implementation from scratch, I built the HelloWorld service and client walked through (very nicely) here. I added endpoints for net.tcp, and the service is working properly end-to-end for both bindings under IIS 7.5 (on Windows 7) in its own ApplicationPool called HW.
What I'm trying to get working is the announced AutoStart and Preload (or "pre-warm caching") features. I've followed the instructions laid out here and here (quite similar to one another, but always good to have a second opinion) very closely. Which means I
1) Set the application pool startMode...
<applicationPools>
<!-- ... -->
<add name="HW" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" />
</applicationPools>
2) ...enabled serviceAutoStart and set a pointer to my serviceAutoStartProvider
<site name="HW" id="2">
<application path="/" applicationPool="HW" serviceAutoStartEnabled="true" serviceAutoStartProvider="PreWarmMyCache" />
<!-- ... -->
</site>
3) ...and named said provider, with the GetType().AssemblyQualifiedName of the class listed in its entirety below
<serviceAutoStartProviders>
<add name="PreWarmMyCache" type="MyWCFServices.Preloader, HelloWorldServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</serviceAutoStartProviders>
using System;
namespace MyWCFServices
{
public class Preloader : System.Web.Hosting.IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(#"C:\temp\PreloadTest.txt");
sw.WriteLine("Preload executed {0:G}", DateTime.Now);
sw.Close();
}
}
}
Alas, all this manual configuration, plus a couple iisreset calls, and I get nothing. No w3wp.exe process firing up in Task Manager (though I get it if I launch the HelloWorldClient), no text file, and above all, no satisfaction.
There is a frustratingly scant amount of discussion about this feature, either on SO or the wider web, and the few similar questions here got little attention, all of which rings an alarm bell or two. Perhaps needlessly though--any experts out there who have been down this very road a time or two care to chime in? (Happy to offer up the entire solution if you can suggest a good place to host it.)
EDIT: I tried resetting that path in the Preload method to the relative App_Data folder (another SO answer suggested that), didn't matter. Also, I learned the w3wp.exe process fires on a simple browse to the localhost. The process consumes an impressive 17MB of memory to serve up its single tiny OperationContract, while for the price offering zero Preload value. 17MB of ColdDeadCache.
This is a slightly different approach for your problem:
Use Windows Server AppFabric for service auto-start
Use WCF infrastructure to execute custom startup code
Re 1: The Appfabric AutoStart feature should just work out of the box (provided you're not using MVC's ServiceRoute to register your services, they MUST be specified either in the Web.config's serviceActivations section or using physical *.svc files.
Re 2: To inject custom startup code into the WCF pipeline you could use an attribute like this:
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace WCF.Extensions
{
/// <summary>
/// Allows to specify a static activation method to be called one the ServiceHost for this service has been opened.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class ServiceActivatorAttribute : Attribute, IServiceBehavior
{
/// <summary>
/// Initializes a new instance of the ServiceActivatorAttribute class.
/// </summary>
public ServiceActivatorAttribute(Type activatorType, string methodToCall)
{
if (activatorType == null) throw new ArgumentNullException("activatorType");
if (String.IsNullOrEmpty(methodToCall)) throw new ArgumentNullException("methodToCall");
ActivatorType = activatorType;
MethodToCall = methodToCall;
}
/// <summary>
/// The class containing the activation method.
/// </summary>
public Type ActivatorType { get; private set; }
/// <summary>
/// The name of the activation method. Must be 'public static void' and with no parameters.
/// </summary>
public string MethodToCall { get; private set; }
private System.Reflection.MethodInfo activationMethod;
#region IServiceBehavior
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
serviceHostBase.Opened += (sender, e) =>
{
this.activationMethod.Invoke(null, null);
};
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
// Validation: can get method
var method = ActivatorType.GetMethod(name: MethodToCall,
bindingAttr: System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public,
callConvention: System.Reflection.CallingConventions.Standard,
types: Type.EmptyTypes,
binder: null,
modifiers: null);
if (method == null)
throw new ServiceActivationException("The specified activation method does not exist or does not have a valid signature (must be public static).");
this.activationMethod = method;
}
#endregion
}
}
..which can be used like this:
public static class ServiceActivation
{
public static void OnServiceActivated()
{
// Your startup code here
}
}
[ServiceActivator(typeof(ServiceActivation), "OnServiceActivated")]
public class YourService : IYourServiceContract
{
}
That's the exact approach we've been using for quite a while and on a large number of services. The extra benefit of using a WCF ServiceBehavior for custom startup code (as opposed to relying on the IIS infrastructure) is that it works in any hosting environment (incl. self-hosted) and can be more easily tested.
I know this sounds absurd but I faced the same issue (w3wp.exe not firing automatically after making the config changes) and it was because I hadn't run the text editor in Admin mode when I was editing the applicationHost.config file. Stupid mistake on my part.
In my defense I was using Notepad++ which told me it was saving when it actually wasn't.
I've done the same. it works...
In preload method I have some code copied from a nice white paper available here!
Preload method looks like...
public void Preload(string[] parameters)
{
bool isServceActivated = false;
int attempts = 0;
while (!isServceActivated && (attempts <10))
{
Thread.Sleep(1 * 1000);
try
{
string virtualPath = "/Test1/Service1.svc";
ServiceHostingEnvironment.EnsureServiceAvailable(virtualPath);
isServceActivated = true;
}
catch (Exception exception)
{
attempts++;
//continue on these exceptions, otherwise fail fast
if (exception is EndpointNotFoundException ||
exception is ServiceActivationException ||
exception is ArgumentException)
{
//log
}
else
{
throw;
}
}
}
}
Maybe you are on a 64-bit system? There is a known "feature" in Windows where the save gets redirected to the 32 bit folder and thus no changes will be picked up
(I have converted my comment to an answer as answers might be easier to find)

SharePoint 2010 event receiver,List Item Events, Document library,event ItemAdded not firing

in SharePoint Server 2010 i have a document library and i want to create sub-folders every time a folder created, i have a code snippet but it's not working, i tried to debug but also the event isn't firing, could any one help me please and here is my code:
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item was added.
/// </summary>
private string[] subFolders = new string[] { "sub-folder1", "sub-folder2", "sub folder3" };
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
SPWeb web = properties.OpenWeb();
SPDocumentLibrary ProductsLibrary = (SPDocumentLibrary)web.Lists[properties.ListId];
if (properties.ListItem.ContentType.Name.ToLower() == "new content type" && properties.ListItem.Folder.ParentFolder.ToString() == ProductsLibrary.RootFolder.ToString())
{
string Url = properties.ListItem.ParentList.RootFolder.ServerRelativeUrl.ToString();
SPFolder libFolder = ProductsLibrary.RootFolder.SubFolders[properties.ListItem.Name];
string newFolderUrl = (web.Url + "/" + libFolder.ToString());
foreach (string subfolder in subFolders)
{
SPListItem newSubFolder = ProductsLibrary.Items.Add(newFolderUrl, SPFileSystemObjectType.Folder, subfolder);
newSubFolder.Update();
}
}
}
}
thank you
the solution is to opent the elements.xml and replace the
with the and the code will run perfectly.
Make sure
you have added this event receiver as part of a feature
the feature containing this event receiver is activated
Event wont fire, if you have not followed the above steps