Create SharePoint Remote Event Receiver from C# code - c#

I have a sharepoint site with some OOB lists (documents and tasks).
I want to catch list changes in my program.
I tried to create WCF service and Remote Event Reciver (RER) via CSOM for this service, but no messages were catched by the WCF service.
The WCF service and RER are created in simple C# application (console application).
Class for WCF service
public class RemoteEventService : Microsoft.SharePoint.Client.EventReceivers.IRemoteEventService
{
public void ProcessOneWayEvent(SPRemoteEventProperties properties)
{
// some code here
}
public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
{
SPRemoteEventResult result = null;
ClientContext context = null;
// some code here
return result;
}
}
WCF-service creation
using (ServiceHost host = new ServiceHost(typeof(RemoteEventService)))
{
host.Open();
host.Description.Behaviors.Find<ServiceAuthorizationBehavior>().ImpersonateCallerForAllOperations = true;
Console.WriteLine("Started service at " + host.BaseAddresses[0].ToString());
Console.WriteLine("Press <enter> to terminate the Application");
Console.ReadKey(true);
}
Remote Event receiver creation
// check that RER doesn't exist
EventReceiverDefinitionCreationInformation receiverAdded =
new EventReceiverDefinitionCreationInformation();
receiverAdded.EventType = EventReceiverType.ItemAdded;
receiverAdded.ReceiverUrl = SERVICE_URL;
receiverAdded.ReceiverName = "TestDocReceiverAdded";
receiverAdded.Synchronization = EventReceiverSynchronization.Asynchronous;
docList.EventReceivers.Add(receiverAdded);
context.ExecuteQuery();
The RER was created (it is available in debug check on next run of my application) but WCF-service didn't catch any messages.
I have checked that WCF-serivce is available from network where Shapoint Site is hosted.
Im not sure if the user (that is used to connect to sharepoint in my app) have enough permissions to manage sharepoint OOB lists.
Is it posiable to add RER to sharepoint OOB list from NOT sharepoint-app?
If no what is the best way to catch list changes in my program?

Related

How to keep common name of SSL while changing port wss

I have a problem here. I created a windows app that requires interaction between browser and desktop apps. In the desktop app, I include WebSocket Secure made by [Dave](WebSocket Server in C#).
I have a valid pfx file. While using the default port (443), everything runs smoothly. The URL shows the CN of the SSL. My window app then has to use other port other than default ones (443), when I change in setting it runs not as per CN of the SSL but instead localhost:portnum. how to make it run using CN in ports other than 443? Please help.
I will try to answer this.
I have checked the link that you have pasted and came across the following code snippet:
private static void Main(string[] args){
IWebSocketLogger logger = new WebSocketLogger();
try
{
string webRoot = Settings.Default.WebRoot;
int port = Settings.Default.Port;
// used to decide what to do with incoming connections
ServiceFactory serviceFactory = new ServiceFactory(webRoot, logger);
using (WebServer server = new WebServer(serviceFactory, logger))
{
server.Listen(port);
Thread clientThread = new Thread(new ParameterizedThreadStart(TestClient));
clientThread.IsBackground = false;
clientThread.Start(logger);
Console.ReadKey();
}
}
catch (Exception ex)
{
logger.Error(null, ex);
Console.ReadKey();
}
}
Within the try block there is this code line:
int port = Settings.Default.Port;
Maybe trying setting that to an auto assign port fix your problem.

Access web service in window phone 8

I'm trying to access web service in window phone. But I cannot find any particular method to access this web service. I'm just creating web service method below
[WebMethod]
public string ListCategory(int Id, string JsonXml)
{
tidybeans.DAL.Category category = new tidybeans.DAL.Category();
if (JsonXml.ToLower() == ("Json").ToLower())
return CreateJsonParameters(category.GetAllDS(Id));
else if (JsonXml.ToLower() == ("xml").ToLower())
return ConvertDatatableToXML(category.GetAllDS(Id));
else
return "Please enter the type";
}
Now I'm not able to find any method to consume web service in window phone 8 application.
Add the web service as a service reference to your project. instantiate its soap client and use it to call the web service method
Windows phone uses asynchronous operations
Example:
ExampleService.MyWebServiceSoapClient client = new ExampleService.MyWebServiceSoapClient();
(in your method)
client.ListCategoryCompleted += client_ListCategoryCompleted;
client.ListCategoryAsync(Id,JsonXml);
(the listcategorycompleted method)
void client_ListCategoryCompleted(object sender, ExampleService.ListCategoryCompletedEventArgs e)
{
//you can hanlde the result here
//txtDisplay.Text = e.Result;
}
ExampleService is the name for the service reference

Using Web API for a Windows Service to Receive Commands and Perform Tasks via Polling?

I have a project where I need to create a windows service that, when instructed via a command, will perform various tasks. This server would run on multiple servers and would effectively perform the same kind of tasks when requested.
For example, I would like to have a Web API service that listens for requests from the servers.
The service running on the server would send a query to Web API every 25 secs or so and pass to it its SERVERNAME. The Web API logic will then look up the SERVERNAME and look for any status updates for various tasks... I.E., if a status for a DELETE command is a 1, the service would delete the folder containing log files... if a status for a ZIP command is a 1, the service would zip the folder containing log files and FTP them to a centralized location.
This concept seems simple enough, and I think I need a nudge to tell me if this sounds like a good design. I'm thinking of using .NET 4.5 for the Windows Service, so that I can use the HttpClient object and, of course, .NET 4.5 for the Web API/MVC project.
Can someone please get me started on what a basic Web API woudld look like provide status updates to the Windows services that are running and issue commands to them...
I'm thinking of having a simple MVC website that folks will have a list of servers (maybe based on a simple XML file or something) that they can click various radio buttons to turn on "DELETE", "ZIP" or whatever, to trigger the task on the service.
I do something similar. I have a main Web API (a Windows Service) that drives my application and has a resource called /Heartbeat.
I also have a second Windows Service that has a timer fire every 30 seconds. Each time the timer fires it calls POST /heartbeat. When the heartbeat request is handled, it goes looking for tasks that have been scheduled.
The advantage of this approach is that the service makes the hearbeat request is extremely simple and never has to be updated. All the logic relating to what happens on a heartbeat is in the main service.
The guts of the service are this. It's old code so it is still using HttpWebRequest instead of HttpClient, but that's trivial to change.
public partial class HeartbeatService : ServiceBase {
readonly Timer _Timer = new System.Timers.Timer();
private string _heartbeatTarget;
public HeartbeatService() {
Trace.TraceInformation("Initializing Heartbeat Service");
InitializeComponent();
this.ServiceName = "TavisHeartbeat";
}
protected override void OnStart(string[] args) {
Trace.TraceInformation("Starting...");
_Timer.Enabled = true;
_Timer.Interval = Properties.Settings.Default.IntervalMinutes * 1000 * 60;
_Timer.Elapsed += new ElapsedEventHandler(_Timer_Elapsed);
_heartbeatTarget = Properties.Settings.Default.TargetUrl;
}
protected override void OnStop() {
_Timer.Enabled = false;
}
private void _Timer_Elapsed(object sender, ElapsedEventArgs e) {
Trace.TraceInformation("Heartbeat event triggered");
try {
var httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(_heartbeatTarget);
httpWebRequest.ContentLength = 0;
httpWebRequest.Method = "POST";
var response = (HttpWebResponse)httpWebRequest.GetResponse();
Trace.TraceInformation("Http Response : " + response.StatusCode + " " + response.StatusDescription);
} catch (Exception ex) {
string errorMessage = ex.Message;
while (ex.InnerException != null) {
errorMessage = errorMessage + Environment.NewLine + ex.InnerException.Message;
ex = ex.InnerException;
}
Trace.TraceError(errorMessage);
}
}
}
You can do it with ServiceController.ExecuteCommand() method from .NET.
With the method you can sand custom command to windows' service.
Then in your service you need to implement ServiceBase.OnCustomCommand() to serve incomming custom command event in service.
const int SmartRestart = 8;
...
//APPLICATION TO SEND COMMAND
service.ExecuteCommand(SmartRestart);
...
//SERVICE
protected override void OnCustomCommand(int command)
{
if (command == SmartRestart)
{
// ...
}
}

Listening to Events in the calendar from more than one person using EWS API

Simply I would like to receive a notification every time someone added a new appointment or made any changes on what he/she has.
The only way I know how to do it , is by using
service.SubscribeToStreamingNotifications
but the problem here that it only listens to the account that the service is bound to like in this way
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP2)
{
Credentials = new WebCredentials(userName, password)
};
service.SubscribeToStreamingNotifications(new FolderId[]
{
WellKnownFolderName.Calendar
}, EventType.FreeBusyChanged, EventType.Deleted);
I have solved this problem by creating a list of services each service is bounded to different user and the application should listen to each of them.
The problem with this way is that I need to have the password of each account I wont to listen to its events, which is not possible in real world.
so is there any way to deal with that ?
I have solved this problem, by creating a list of services, all the services are a clone of the main ExchangeService, with the same credentials for the admin account, but they are impersonated to the other accounts.
NOTE: You need to setup the server so it allows impersonation.
private void ImpersonateUsers(ICollection<string> userSmtps)
{
if (userSmtps != null)
if (userSmtps.Count > 0)
{
foreach (var userSmtp in userSmtps)
{
if (_services.ContainsKey(userSmtp)) continue;
var newService = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
try
{
var serviceCred = ((System.Net.NetworkCredential)(((WebCredentials)(_services.First().Value.Credentials)).Credentials));
newService.Credentials = new WebCredentials(serviceCred.UserName, serviceCred.Password, serviceCred.Domain);
newService.AutodiscoverUrl(serviceCred.UserName + "#" + serviceCred.Domain, RedirectionUrlValidationCallback);
newService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userSmtp);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
_services.Add(userSmtp, newService);
}
}
}
Where userSmtps is a list of the email addresses I want to impersonate and _services is the dictionary of services where the first member is the main service.
you will have to create a service instance per user. There is no way to subscribe to other users folder.
But instead of StreamingNotifications you can use Pull and Push-Subscriptions too.
Something like this:
List<FolderId> folders = new List<FolderId>();
folders.Add(new FolderId(WellKnownFolderName.Calendar));
PullSubscription subscription = = service.SubscribeToPullNotifications(folders, 1440, watermark, EventType.Created, EventType.Deleted, EventType.Modified, EventType.Moved, EventType.NewMail);
Some time later....
GetEventsResults currentevents = m_subscription .GetEvents();

connecting to ServiceContract?

Continuing to learn WCF, I'm trying to write a small program that would with a click of a button take the work from texbox1 , pass it to ServiceContract and get back its length.
Here's how far I got.
Form1.cs:
...
wcfLib.Service myService = new wcfLib.Service();
private void button1_Click(object sender, EventArgs e)
{
textBox2.Text = Convert.ToString( myService.go(textBox1.Text) );
}
...
and the wcf file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace wcfLib
{
[ServiceContract]
public interface IfaceService
{
[OperationContract]
int wordLen(string word);
}
public class StockService : IfaceService
{
public int wordLen(string word)
{
return word.Length;
}
}
public class Service
{
public int go( string wordin )
{
ServiceHost serviceHost = new ServiceHost(typeof(StockService), new Uri("http://localhost:8000/wcfLib"));
serviceHost.AddServiceEndpoint(typeof(IfaceService), new BasicHttpBinding(), "");
serviceHost.Open();
int ret = **///// HOW SHOULD I PASS wordin TO StockService to get word.Length in return?**
serviceHost.Close();
return ret;
}
}
}
what I can't figure out right now, is how do I pass the wordin variable above into the ServiceContract?
You need to create the client in your form and call wordLen() directly... only a class that inherits from IfaceService can be called as a WCF service. So:
// You'll have to create references to your WCF service in the project itself...
// Right-click your form project and pick 'Add Service Reference', picking
// 'Discover', which should pick up the service from the service project... else
// enter http://localhost:8000/wcfLib and hit 'Go'.
// You'll have to enter a namespace, e.g. 'MyWcfService'... that namespace is
// used to refer to the generated client, as follows:
MyWcfService.wcfLibClient client = new MyWcfService.wcfLibClient();
private void button1_Click(object sender, EventArgs e) {
// You really shouldn't have the client as a member-level variable...
textBox2.Text = Convert.ToString(client.wordLen(textBox1.Text));
}
If your Service class is meant to host the WCF Service, it needs to be its own executable and running... put the code you have in go() in Main()
Or host your WCF Service in IIS... much easier!
Edit
IIS = Internet Information Services... basically hosting the WCF Service over the web.
To host in IIS, create a new project, "WCF Service Application". You'll get a web.config and a default interface and .svc file. Rename these, or add new items, WCF Service, to the project. You'll have to read up a bit on deploying to IIS if you go that route, but for debugging in Visual Studio, this works well.
To split into two applications, just make the form its own project... the service reference is set through the application's config file; you just point it to the address of the machine or website, e.g. http://myintranet.mycompany.com:8000/wcflib or http://myserver:8000/wcflib.
Thanks for the vote!
You've definitely got things back-to-front. You don't want to create the ServiceHost in your Go method, or at least, you'd never create it in any method invoked by the client, because how could the client call it if the service hasn't been created yet?
A service in WCF is started, and THEN you can invoke its methods from a remote client. EG, this is your Main() for the service:
ServiceHost serviceHost = new ServiceHost(typeof(StockService), new Uri("http://localhost:8000/wcfLib"));
serviceHost.AddServiceEndpoint(typeof(IfaceService), new BasicHttpBinding(), "");
serviceHost.Open();
Console.WriteLine("Press return to terminate the service");
Console.ReadLine();
serviceHost.Close();
Then for your client you'd use "Add Service Reference" in Visual Studio (right-click on the Project in Solution Explorer to find this menu option) and enter the address for the service. Visual Studio will create a proxy for your service, and this is what you'd instantiate and use on the client. EG:
MyServiceClient client = new MyServiceClient();
textBox2.Text = Convert.ToString( client.wordLen(textBox1.Text) );

Categories