How To: Open a Word document from .NET Core web application, edit, and save back to server? - c#

I am looking for modern examples on how to create a SharePoint-like integration with Microsoft Word but in an ASP/C# (.NET Core) web application. In other words, my goal is to click on a Word document from my webpage (file stored on my on-premise server), open in Word (desktop application), makes changes, and save back to the server. When I say SharePoint-like integration, I mean, opening and saving are handled automatically without the user having to be bothered by saving the file locally and manually uploading it back to the server.
I have found others asking the same question but with no concrete response and most were nearly a decade old. Here are some of the articles I found but of no help:
C# and Office integration
How can I open, edit and save a word document with asp.net
https://social.msdn.microsoft.com/Forums/office/en-US/e1928f0b-6922-4f23-a1f9-09835e39f7da/how-to-opensave-word-documents-fromto-in-aspnet-webapi-using-ms-word-application
It looks like the Office Add-in platform (https://learn.microsoft.com/en-us/office/dev/add-ins/overview/office-add-ins#components-of-an-office-add-in) may be of use, but I don't necessarily want a Word add-in added to the ribbon. So not sure this is really what I want.
WebDAV may be what I need as discussed here (https://www.webdavsystem.com/ajaxfilebrowser/programming/opening-docs/open_save_docs_directly_to_server/) but not sure... and the article talks about Office 2007 so seems kind of dated.
Any help in guiding me to example, article, or forum that discusses current approaches to tackle this would greatly be appreciated.
A little more information: clients would be using Edge or Chrome browsers, on Windows 10 boxes, with Office 2016 (or later).

This question is very broad. There looks to be several parts.
A plugin that can be configured to communicate with a webservice
An Api that consumes data from the plugin
The plugin should be able to save automatically
Here is some related documentation though some are specific to Excel, though may be able to be repurposed for Word
Also note that Office plugin development is JavaScript and/or TypeScript.
https://learn.microsoft.com/en-us/office/dev/add-ins/excel/custom-functions-web-reqs
https://learn.microsoft.com/en-us/office/dev/add-ins/excel/custom-functions-batching
https://learn.microsoft.com/en-us/javascript/api/word/word.document?view=word-js-preview#save__
There is not any code here so even writing a specific function would be making several assumptions, but from the documentation (with a couple add ins):
// Run a batch operation against the Word object model.
Word.run(function (context) {
// Create a proxy object for the document.
var thisDocument = context.document;
// Queue a command to load the document save state (on the saved property).
context.load(thisDocument, 'saved');
// Synchronize the document state by executing the queued commands,
// and return a promise to indicate task completion.
return context.sync().then(function () {
if (thisDocument.saved === false) {
// Queue a command to save this document.
thisDocument.save();
// Synchronize the document state by executing the queued commands,
// and return a promise to indicate task completion.
return context.sync().then(function () {
//
// CODE to send your data to your server(s) via
// API (post request, or something similar)
//
console.log('Saved the document');
});
} else {
console.log('The document has not changed since the last save.');
}
});
})
.catch(function (error) {
console.log("Error: " + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log("Debug info: " + JSON.stringify(error.debugInfo));
}
});

Related

Scan Uploaded File using Sophos Labs Intelix in c#

I am new to SophosLabs Intelix. I am trying to build a sample in my ASP .Net Application(webforms/MVC) in which I want to run an Antivirus Scan on the uploaded file by the User. If the Uploaded file is clean I want to upload it to the server else I want to cancel the operation. I want to specifically use SophosLabs Intelix for the functionality. It would be great if someone can guide me regarding this functionality. A code sample in C# would be appreciated a lot.
Thanks in advance for your help.
Sample:
if(file.HasFile)
{
//run an antivirus scan
//result
if(result == NoThreat){
//Uploaded Successfully
}
else{
//File contains a virus. Upload failed!
}
}
else{
//Please select a file to upload!
}
I suggest to start with the implementation of OAUTH 2 authentication request. You can find some ideas here: How do I get an OAuth 2.0 authentication token in C#
As soon as you have the access_token you can use if for /reports/?sha256=... query.
It may return the report immediately.
If it does not return any data (404) this request was free and you can POST the file to the root endpoint "/" for analysis.
It can take a few seconds/minutes, during that you should poll the report from /reports/{job_id} endpoint as long as you get it.
If you cannot wait minutes for decision data, you may use the File Hash Lookup API as well that returns immediately.
It may give a reputationScore between 30..69 so cannot decide how dangerous the file is, but in this case you can still perform a static or dynamic analysis on it.

Cannot save the attachment. The operation failed. An object cannot be found error in server

I am trying of save attachment of outlook mail, i am able to save attachment when it have data. but for empty attachment its throws exception that Cannot save the attachment. The operation failed. An object cannot be found.
In my local i am able to save but this issue is coming in server.
void saveattachments(Outlook.Attachment attachment)
{
string currentTime = DateTime.Now.ToString("hh_MM_ss");
try
{
attachment.SaveAsFile(GetConfigSettings("attachmentPath") + "\\attachment_" + "_" + currentTime + "_" + attachment.FileName);
}
catch(exception e)
{}
}
why it throws error in server for blank file but not in local.
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. Read more about that in the Considerations for server-side Automation of Office article.
You may consider using MAPI instead (a low-level API on which Outlook is based on).

Remoting Automation of MS Office on the server

I'm warning you, that yhis question will seems to be very strange for a lot of people:) But I have to post it because my project manager is teeling me that a technical solution exist, even if for me it doesn't.
What we have:
A Windows 7 Console Application with no UI, with our C# application running and no Office and Interop on it
a Windows 2012 server, with Ms Office 2010 + Interop installed on it (also with IIS and .NET of course)
What my PM want (and I told him it is not possible) :
From my C# client application
Automate "Ms office" installed on the server
Automate means "Save" or "print" a doc file to a network printer.
Of course the Ms office process had to run on the server
This kind of solution of "remote Ms Office automation is possible" seems to be impossible for me. But maybe I am wrong, it can be possiblbe using DCOM, WCF, or something else?
Anyone can confirm I am right please ;)
As you already learned from the comments, automating the desktop version of any of the Office applications is bad for several reasons. The details can be found in the Knowledge base article KB257757 Considerations for server-side Automation of Office. The main take away from that article is:
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
But as you are still insisting, consider the following example as a very simple, naive, not to be used near production proof-of-concept that enables you to quickly run into all problems mentioned in the KB article.
In a fresh solution create a WCF Service application and a Console Application. In the WCF application add the following interface:
[ServiceContract]
public interface IPrintService
{
[OperationContract]
string Print(Stream wordDoc);
}
and have a service implement that. Make sure to add a reference to Microsoft.Office.Interop.Word that you can find in the COM tab of the Add Reference dialog.
public class PrintService : IPrintService
{
public string Print(Stream wordDocStream)
{
// copy our stream to a local file
var tempFile = Path.GetTempFileName();
using(var file = File.Create(tempFile))
{
wordDocStream.CopyTo(file);
}
// start word
var wordApp = new Microsoft.Office.Interop.Word.Application();
// setup printer
wordApp.ActivePrinter = "Canon LBP3010/LBP3018/LBP3050";
// open, collect data, print and close
var doc = wordApp.Documents.Open(tempFile);
doc.PrintOut();
var res = doc.Words.Count;
doc.Close(false);
// quit word
wordApp.Quit(false);
// delete temp file
File.Delete(tempFile);
return String.Format("{0} words", res);
}
}
You can see here a barebone solution to print a document that is sent as a stream to the Service. The service copies the stream to a file, starts Word, Opens the file, prints the document, get some data from the document and tears down and cleans up hen finished.
The client is straight forward:
using(var client = new PrintService.PrintServiceClient())
{
using(var file = File.Open(#"small.docx", FileMode.Open))
{
var response = client.Print(file);
Console.WriteLine(response);
}
}
This is technically all there is that is needed to print a Word document from a service. This runs without much problems on the dev server. If you run this on IIS you'll probably have to make sure that the account used as an identity in the AppPool is a "user" that can start Word, is allowed to access the printers etc. I already ran into one known issue: I used the XPS Print driver which caused a dialog to popup. That is something you can't have on a server and there is no real way to prevent or detect that.
Remember that this service interface only allows for a stream to be sent. If you want to add extra data you'll have to use a message contract as is explained on msdn in Large Data and Streaming. Your contract would have to look like this in that case:
[MessageContract]
public class UploadStreamMessage
{
[MessageHeader]
public string appRef;
[MessageBodyMember]
public Stream data;
}
If you run all this, (stress)test, consider deployment and install I'm sure you'll convince anyone that this isn't a good idea.

SharePoint Claims-Authentication, Cookies, C#, and Excel-DLL/tld

The basic concept of the project is it accesses SharePoint, verifies a certain file exists, verifies the file is NOT locked by another user, and then, if those two conditions are met, excel opens the file up and does some stuff with it, then saves the file and closes it again.
The issue is at the point where the program accesses SharePoint and runs through the verification steps. Initially, my first crack at this was directly from VBA using SOAP, and, until Microsoft decided to downgrade SharePoint to 2013 from 2010, it worked quite well, meaning now, I'm into using Visual Studio and C# to accomplish the same thing that SOAP was doing in SP2010.
I've attempted implementing the code found here: http://www.vrdmn.com/2013/01/authenticating-net-client-object-model.html, however I can't get it to work. What I did manage to get working was the 2010 authentication model which pops up a browser window, checks for valid cookies, and, if it finds them, reads the cookies, otherwise prompts the user to log into SharePoint and then closes the browser and continues on.
public CookieCollection Show()
{
if (string.IsNullOrEmpty(this.LoginPageUrl)) throw new ApplicationException(Constants.MSG_NOT_CLAIM_SITE);
// navigate to the login page url.
this.webBrowser.Navigate(this.LoginPageUrl);
DisplayLoginForm = new Form();
DisplayLoginForm.SuspendLayout();
// size the login form
int dialogWidth = Constants.DEFAULT_POP_UP_WIDTH;
int dialogHeight = Constants.DEFAULT_POP_UP_HEIGHT;
if (PopUpHeight != 0 && PopUpWidth != 0)
{
dialogWidth = Convert.ToInt32(PopUpWidth);
dialogHeight = Convert.ToInt32(PopUpHeight);
}
DisplayLoginForm.Width = dialogWidth;
DisplayLoginForm.Height = dialogHeight;
DisplayLoginForm.Text = this.fldTargetSiteUrl;
DisplayLoginForm.Controls.Add(this.webBrowser);
DisplayLoginForm.ResumeLayout(false);
//DisplayLoginForm.Show();
Application.Run(DisplayLoginForm);
// see ClaimsWebBrowser_Navigated event
//DisplayLoginForm.Dispose();
return this.fldCookies;
}
The problem comes about with the Application.Run(DisplayLoginForm). If I step through the code line-by-line, everything works fine, and I get the results I need within my VBA code. However, if I run the program with F5 (either by building it in Debug mode or in Release mode), Application.Run(DisplayLoginForm) kills the application (and Excel along with it) once the cookie jar (my term, and most likely not a computer term) has been examined for valid cookies.
You can see in the code, I attempted to use DisplayLoginForm.Show(); rather than Application.Run, however I kept getting null references to the file I'm trying to find, so that approach does not work either.
So here's the question:
How do I go about popping up a web browser (which is obviously set up as a windows form), look for the cookies, prompt the user if needed, close the web browser and remain alive long enough to return the appropriate values (file.exists and file.islockedbyuser.email, both of which are in functions called by the VBA and both of which work just fine) to excel, and then finish up the program without shutting Excel down in the process?
The answer to this question is to set up a new and separate thread on which to operate the browser and login sequence, returning to the main thread (and the thread Excel is running on) the context with the credentials, with which the file can be queried.

Delete Inbox Messages with TweetSharp

I'm using the latest stable built of TweetSharp from codeplex in a VS2008 C# project. I'm writing the project in terms of TwitterService not FluentTwitter.
I have an application that authenticates, then acts as a listener. It sits around and polls Twitter at regular interval looking for direct messages. After I have fetched the latest direct messages (which works fine), I process them and do stuff, then I want to remove them from my inbox, so I never reprocess them again.
The first place I looked was TwitterServer.DeleteDirectMessage(int msgId), however, since I didn't author the DMs, I clearly can't delete them. I know there is a way to do this, because if you log in to the Twitter webpage you can simply delete DMs one by one from your inbox.
Two questions:
1. How to delete DMs from my inbox?
2. Where is complete documentation? (Apologies if this is obvious and I missed it, but it's not under the "Documentation" tab on TweetSharp's codeplex site. The only thing under "Documentation" is several primitive examples.)
//Authenticate...
//Declarations:
string message = null;
List<string> messages = new List<string>();
IEnumerable<TwitterDirectMessage> directMessages = service.ListDirectMessagesReceived();
//Fetch all current direct message:
foreach (TwitterDirectMessage directMessage in directMessages)
{
//Store each message into a list, in reverse older:
message = /*"[" + directMessage.CreatedDate.ToString() + "]" +*/ directMessage.Text;
messages.Insert(0, message);
//Delete each DM to ensure that is is never fetched again:
// ??
}
//Do stuff with DMs
Do you really want to delete DMs from the server? What if the user will go back to twitter.com and want to look them up there?
Another approach could be for you to keep track of DMs that have been displayed before and filter them out later on the client side before re-processing.

Categories