Exchange Web Services find item by unique id - asp.net

I just started using Microsoft Exchange Web Services for the first time. Want I want to be able to do is the following:
Create Meeting
Update Meeting
Cancel/Delete Meeting
These meetings are created in an ASP.NET MVC application and saved into a SQL Server database. I simply wish to integrate this with the on site Exchange Server. So far, I'm able to created my meeting with the following code:
public static Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
{
var tcs = new TaskCompletionSource<string>();
try
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = CredentialCache.DefaultNetworkCredentials;
//service.UseDefaultCredentials = true;
// I suspect the Service URL needs to be set from the user email address because this is then used to set the organiser
// of the appointment constructed below. The Organizer is a read-only field that cannot be manually set. (security measure)
service.AutodiscoverUrl(from);
//service.Url = new Uri(WebConfigurationManager.AppSettings["ExchangeServer"]);
Appointment meeting = new Appointment(service);
meeting.Subject = subject;
meeting.Body = "<span style=\"font-family:'Century Gothic'\" >" + body + "</span><br/><br/><br/>";
meeting.Body.BodyType = BodyType.HTML;
meeting.Start = begin;
meeting.End = end;
meeting.Location = location;
meeting.ReminderMinutesBeforeStart = 60;
foreach (string attendee in to)
{
meeting.RequiredAttendees.Add(attendee);
}
meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);
tcs.TrySetResult(meeting.Id.UniqueId);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
This successfully creates my meeting, places it into the user's calendar in outlook and sends a meeting request to all attendees. I noticed the following exception when attempting to call meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy); twice:
This operation can't be performed because this service object already has an ID. To update this service object, use the Update() method instead.
I thought: Great, it saves the item in exchange with a unique id. I'll save this ID in my application's database and use it later to edit/cancel the meeting. That is why I return the id: tcs.TrySetResult(meeting.Id.UniqueId);
This is saved nicely into my application's database:
Now, I am attempting to do the next part where I update the meeting, but I cannot find a way to search for the item based on the unique identifier that I'm saving. An example I found on code.msdn uses the service.FindItems() method with a query that searches the subject:
string querystring = "Subject:Lunch";
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, querystring, view);
I don't like this. There could be a chance that the user created a meeting outside of my application that coincidentally has the same subject, and here come's my application and cancel's it. I tried to determine wether it's possible to use the unique id in the query string, but this does not seem possible.
I did notice on the above query string page that the last property you can search on is (property is not specified) that searches in "all word phase properties.". I tried thus simply putting the id into the query, but this returns no results:
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Calendar, "AAMkADJhZDQzZWFmLWYxYTktNGI1Yi1iZTA5LWVmOTE3MmJiMGIxZgBGAAAAAAAqhOzrXRdvRoA6yPu9S/XnBwDXvBDBMebkTqUWix3HxZrnAAAA2LKLAAB5iS34oLxkSJIUht/+h9J1AAFlEVLAAAA=", view);

Use the Appointment.Bind static function, providing a service object and the ItemId saved in your database. Be aware with meeting workflow (invite, accept, reject) can re-create a meeting on the same calendar with a new ItemId. But if you are just looking at the meeting you make on your own calendar, you should be OK.

Related

Login authentication to asp.net and postgresql

I have tried to implement login page in ASP.NET Core MVC and using postgresql as database.
It should check whether user exits in the database table of postgresql and verify, so what is the query to search for user in database and made them sign in?
I have written my code like this:
public IActionResult Login(string seller_email, string seller_password)
{
using var connection = new NpgsqlConnection(connString);
connection.Open();
string main_query = String.Format(#"select exists(select 1 from public.""sellers"" where ""seller_email""='{0}')", seller_email);
using var command_main = new NpgsqlCommand(main_query, connection);
int result_main = command_main.ExecuteNonQuery();
if (result_main < 0)
{
return View(nameof(Create));
}
else
{
return View(nameof(Sign));
}
}
There is a seller table in the database, so just have to check seller exists or not - if exists the have to create a view for it
You are doing a select query, so you must use a command.ExecuteReader.
The ExecuteNonQuery is to be used with statements that update/insert/delete records.
BUT, most importantly, don't concatenate user submitted values into the query string, as it opens the door to SQL injections. Instead, used a parameter.
See the getting started doc for a simple example.

WCF Transaction with multiple inserts

When creating a user, entries are required in multiple tables. I am trying to create a transaction that creates a new entry into one table and then pass the new entityid into the parent table and so on. The error I am getting is
The transaction manager has disabled its support for remote/network
transactions. (Exception from HRESULT: 0x8004D024)
I believe this is caused by creating multiple connections within a single TransactionScope, but I am unsure on what the best/most efficient way of doing this is.
[OperationBehavior(TransactionScopeRequired = true)]
public int CreateUser(CreateUserData createData)
{
// Create a new family group and get the ID
var familyGroupId = createData.FamilyGroupId ?? CreateFamilyGroup();
// Create the APUser and get the Id
var apUserId = CreateAPUser(createData.UserId, familyGroupId);
// Create the institution user and get the Id
var institutionUserId = CreateInsUser(apUserId, createData.AlternateId, createData.InstitutionId);
// Create the investigator group user and return the Id
return AddUserToGroup(createData.InvestigatorGroupId, institutionUserId);
}
This is an example of one of the function calls, all the other ones follow the same format
public int CreateFamilyGroup(string familyGroupName)
{
var familyRepo = _FamilyRepo ?? new FamilyGroupRepository();
var familyGroup = new FamilyGroup() {CreationDate = DateTime.Now};
return familyRepo.AddFamilyGroup(familyGroup);
}
And the repository call for this is as follows
public int AddFamilyGroup(FamilyGroup familyGroup)
{
using (var context = new GameDbContext())
{
var newGroup = context.FamilyGroups.Add(familyGroup);
context.SaveChanges();
return newGroup.FamilyGroupId;
}
}
I believe this is caused by creating multiple connections within a single TransactionScope
Yes, that is the problem. It does not really matter how you avoid that as long you avoid it. A common thing to do is to have one connection and one EF context per WCF request. You need to find a way to pass that EF context along.
The method AddFamilyGroup illustrates a common anti-pattern with EF: You are using EF as a CRUD facility. It's supposed to me more like a live object graph connected to the database. The entire WCF request should share the same EF context. If you move in that direction the problem goes away.

CreateEnvelopeFromTemplates - Guid should contain 32 digits with 4 dashes

I am attempting to create a DocuSign envelope from a template document using the CreateEnvelopeFromTemplates method, available within their v3 SOAP API web service. This is being instantiated from a asp.NET v4.0 web site.
Upon calling the method armed with the required parameter objects being passed in. I am recieving an exception from the web service, basically telling me that the Template ID is not a valid GUID.
669393: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Line 14889:
Line 14890: public DocuSignDSAPI.EnvelopeStatus CreateEnvelopeFromTemplates(DocuSignDSAPI.TemplateReference[] TemplateReferences, DocuSignDSAPI.Recipient[] Recipients, DocuSignDSAPI.EnvelopeInformation EnvelopeInformation, bool ActivateEnvelope) {
Line 14891: return base.Channel.CreateEnvelopeFromTemplates(TemplateReferences, Recipients, EnvelopeInformation, ActivateEnvelope);
Line 14892: }
Line 14893:
The template reference, a guid. Must be specified as the "Template" string property against TemplateReference object. This is then added to a dynamic array of TemplateReferences, which is one of the input parameters of the CreateEnvelopeFromTemplates method.
Actual template GUID: f37b4d64-54e3-4723-a6f1-a4120f0e9695
I am building up my template reference object using the following function that i wrote to try and make the functionality reusable:
Private Function GetTemplateReference(ByVal TemplateID As String) As TemplateReference
Dim templateReference As New TemplateReference
Dim guidTemplateID As Guid
With TemplateReference
.TemplateLocation = TemplateLocationCode.Server
If Guid.TryParse(TemplateID, guidTemplateID) Then
.Template = guidTemplateID.ToString
End If
End With
Return TemplateReference
End Function
The TemplateID is being passed in from a appSetting configuration value at the time of the TemplateReferences array instantiation like so...
templateReferences = New TemplateReference() {GetTemplateReference(ConfigurationManager.AppSettings("DocuSignTemplate_Reference"))}
recipients = New Recipient() {AddRecipient("myself#work.email", "My Name")}
envelopeInformation = CreateEnvelopeInformation()
envelopeStatus = client.CreateEnvelopeFromTemplates(templateReferences, recipients, envelopeInformation, True)
As you can see from my GetTemplateReference function I am also parsing the GUID before setting it back as a string so i know its valid. The template is managed and stored at the DocuSign end, hence specifying the document location.
I am referring to their own documentation:
CreateEnvelopeFromTemplates
Why oh why is the method not liking my Template ID? I can successfully use their REST API to call the same method, using their own code samples. Worst case I can make use of this but would rather interact with the web service as I would need to construct all the relevent requests in either XML or JSON.
I would really appreciate if someone could perhaps shed some light on this problem.
Thanks for taking the time to read my question!
Andrew might be spot on with the AccountId mention - are you setting the AccountId in the envelope information object? Also, have you seen the DocuSign SOAP SDK up on Github? That has 5 sample SOAP projects including one MS.NET project. The .NET project is in C# not Visual Basic, but still I think it will be helpful to you. Check out the SOAP SDK here:
https://github.com/docusign/DocuSign-eSignature-SDK
For instance, here is the test function for the CreateEnvelopeFromTemplates() function:
public void CreateEnvelopeFromTemplatesTest()
{
// Construct all the recipient information
DocuSignWeb.Recipient[] recipients = HeartbeatTests.CreateOneSigner();
DocuSignWeb.TemplateReferenceRoleAssignment[] finalRoleAssignments = new DocuSignWeb.TemplateReferenceRoleAssignment[1];
finalRoleAssignments[0] = new DocuSignWeb.TemplateReferenceRoleAssignment();
finalRoleAssignments[0].RoleName = recipients[0].RoleName;
finalRoleAssignments[0].RecipientID = recipients[0].ID;
// Use a server-side template -- you could make more than one of these
DocuSignWeb.TemplateReference templateReference = new DocuSignWeb.TemplateReference();
templateReference.TemplateLocation = DocuSignWeb.TemplateLocationCode.Server;
// TODO: replace with template ID from your account
templateReference.Template = "server template ID";
templateReference.RoleAssignments = finalRoleAssignments;
// Construct the envelope information
DocuSignWeb.EnvelopeInformation envelopeInfo = new DocuSignWeb.EnvelopeInformation();
envelopeInfo.AccountId = _accountId;
envelopeInfo.Subject = "create envelope from templates test";
envelopeInfo.EmailBlurb = "testing docusign creation services";
// Create draft with all the template information
DocuSignWeb.EnvelopeStatus status = _apiClient.CreateEnvelopeFromTemplates(new DocuSignWeb.TemplateReference[] { templateReference },
recipients, envelopeInfo, false);
// Confirm that the envelope has been assigned an ID
Assert.IsNotNullOrEmpty(status.EnvelopeID);
Console.WriteLine("Status for envelope {0} is {1}", status.EnvelopeID, status.Status);
}
This code calls other sample functions in the SDK which I have not included, but hopefully this helps shed some light on what you're doing wrong...
This problem arises when you don't set up the field AccountId. This field can be retrieved from your account. In Docusign's console go to Preferences / API and look here
Where to find AccountID Guid in Docusign's Console
Use API Account ID (which is in GUID format) and you should be OK.

asp.net membership, notify administrators when account about to expire

I have a requirement that a certain email distribution list should be notified every so often (still to be determined) about user accounts that are nearing expiration.
I'm wondering the best way to achieve this, I know its generally a bad idea to spawn another thread within asp.net to handle this type of thing, so I'm thinking maybe a simple service is the way to go but for something so small this seems like it might be slightly overkill.
Ideally I'd like something that doesnt require much babysitting (eg. checking service is running).
I have also suggested having a page in the site with this type of information but it is likely that it could be a few days before this is checked. We also cannot let users extend their own expiration date.
Are there any other viable options.
The best suitable method to work on it according to is
create a application which will select list of all users whose account expiry date is nearby (eg. 10 days from today) as per your requirement.
This application will be scheduled as an daily execution (you will create an exe with log file to display errors raised and total number of emails sent in one execution.)
This application will fetch all the records based on criteria and send the emails to all yours using the basic HTML template. and once the email is sent, you will update a column (notificationFlag) in your database as 1 if you have sent is once in last 10 days. else by default it will be 0
you can schedule the exe by the end of the day at 12:10 am (just incase your database server and webserver is not matching in time) every day. .
This is something I've done which is similar to Prescott's comment on your answer.
I have a website with an administrative page that reports on a bunch of expiration dates.
This page also accepts a QueryString parameter SEND_EMAILS, so anytime an administrative user of the site passes the QueryString parameter SEND_EMAILS=true a bunch of emails go out to all the users that are expiring.
Then I just added a windows scheduled task to run daily and load the page with the SEND_EMAILS=true parameter.
This was the simple code I used to issue the webrequest from the console in the scheduled task:
namespace CmdLoadWebsite
{
class Program
{
static void Main(string[] args)
{
string url = "http://default/site/";
if (args.Length > 0)
{
url = args[0];
}
Console.WriteLine(GetWebResult(url));
}
public static string GetWebResult(string url)
{
byte[] buff = new byte[8192];
StringBuilder sb = new StringBuilder();
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
Stream webStream = response.GetResponseStream();
int count = 0;
string webString;
do
{
count = webStream.Read(buff, 0, buff.Length);
if (count != 0)
{
webString = Encoding.ASCII.GetString(buff, 0, count);
sb.Append(webString);
}
}
while (count > 0);
return(sb.ToString());
}
}
}

Microsoft dynamics CRM 2011: how to generate lead from external contact form

i developed CMS to one of my customers and he wants that when a user fill in the contact form, it will automatically generate lead in his CRM.
what is the easiest way to do that?
by the way, the contact form is ajax and the data is transfered to asmx, so it will be easy to call to CRM webservice or something like that, because i'm already in the server side.
can someone point me to tutorial or some code example?
thanks!
Your best start will be with the SDK available here, which contains example code and the sdk dlls etc...
Here is a page with a quick reference to all the web service endpoints available in the different flavors of CRM 2011.
From the SDK samplepcode\cs\quickstart creating account, but very similar for lead:
// Connect to the Organization service.
// The using statement assures that the service proxy will be properly disposed.
using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri,
serverConfig.HomeRealmUri,
serverConfig.Credentials,
serverConfig.DeviceCredentials))
{
// This statement is required to enable early-bound type support.
_serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
// Instaniate an account object.
// See the Entity Metadata topic in the SDK documentation to determine
// which attributes must be set for each entity.
Account account = new Account { Name = "Fourth Coffee" };
// Create an account record named Fourth Coffee.
_accountId = _serviceProxy.Create(account);
Console.Write("{0} {1} created, ", account.LogicalName, account.Name);
// Retrieve the account containing several of its attributes.
ColumnSet cols = new ColumnSet(
new String[] { "name", "address1_postalcode", "lastusedincampaign" });
Account retrievedAccount = (Account)_serviceProxy.Retrieve("account", _accountId, cols);
Console.Write("retrieved, ");
// Update the postal code attribute.
retrievedAccount.Address1_PostalCode = "98052";
// The address 2 postal code was set accidentally, so set it to null.
retrievedAccount.Address2_PostalCode = null;
// Shows use of a Money value.
retrievedAccount.Revenue = new Money(5000000);
// Shows use of a boolean value.
retrievedAccount.CreditOnHold = false;
// Update the account record.
_serviceProxy.Update(retrievedAccount);
Console.WriteLine("and updated.");

Resources