MSCRM 2011 CloseQuoteRequest Offline - plugins

I wanna close a Quote from a Plugin. Everything works fine online, but if my plugin runs offline in Outlook, i will get an error:
Primary Key must be populated for calls to platform on rich client in offline mode
I close the quote like that:
CloseQuoteRequest req = new CloseQuoteRequest();
req.QuoteClose = myQuote;
req.Value = new OptionSetValue(6);
service.Execute(req);
I traced my plugin while offline and my attributes like the ID of my quote are OK.
Does anyone have some ideas?

the solution is to use a late bound quoteclose entity and provide the activityid guid:
var item = service.retrieve("quote",quoteid, new columnset(true);
var quoteclose = new Entity("quoteclose");
quoteclose.Attributes.Add("quoteid", item.ToEntityReference());
quoteclose.Attributes.Add("subject", "Quote Closed");
quoteclose.Attributes.Add("description", "Quote Closed");
quoteclose.Attributes.Add("quotenumber", item.Attributes["quotenumber"]);
quoteclose.Attributes.Add("ownerid", item.Attributes["ownerid"]);
quoteclose.Attributes.Add("revision", 0);
quoteclose.Attributes.Add("activityid", Guid.NewGuid());
quoteclose.Attributes.Add("actualend", DateTime.Now);
// Close the quote
CloseQuoteRequest closeQuoteRequest = new CloseQuoteRequest()
{
QuoteClose = quoteclose,
Status = new OptionSetValue(5)
};
contextBag.Service.Execute(closeQuoteRequest);

Related

AutoShowTaskpaneWithDocument Word Add-In - We can't find the Taskpane to open

My problem is probably best described in this question:
Auto-opening side-loaded taskpane
But, the answer given won't work for me. I work at a company and setting up a new PC is not an option.
I wrote an Office (Word) Add-In (Office API/JS) and I want it to auto-open when a user opens one of the documents listed on my website. When a user selects a document to download, I open the document on the web server before downloading it and add some extra OpenXML parts in the document using OpenXML to make it open the Add-In. Here's the code:
//params:
// wordDoc - the WordProcessing object being updated
//_WebExtensionStoreReferenceId = GUID of Add-In (the <Id> tag in Add-In manifest)
//_WebExtensionStoreReferenceVersion = "1.0.0.1" - matches version in manifest
//_WebExtensionStoreReferenceStore = path to manifest file
//_WebExtensionStoreReferenceStoreType = "FileSystem"
public static void AddWebExTaskpanesPart(WordprocessingDocument wordDoc,
string _WebExtensionStoreReferenceId, string _WebExtensionStoreReferenceVersion, string _WebExtensionStoreReferenceStore, string _WebExtensionStoreReferenceStoreType)
{
wordDoc.DeletePartsRecursivelyOfType<WebExTaskpanesPart>();
wordDoc.DeletePartsRecursivelyOfType<WebExtensionPart>();
WebExTaskpanesPart webExTaskpanesPart = wordDoc.AddWebExTaskpanesPart();
WebExtensionPart webExtensionPart = webExTaskpanesPart.AddNewPart<WebExtensionPart>("rId1");
We.WebExtension webExtension = new We.WebExtension() { Id = _WebExtensionStoreReferenceId };
webExtension.AddNamespaceDeclaration("we", "http://schemas.microsoft.com/office/webextensions/webextension/2010/11");
We.WebExtensionStoreReference webExtensionStoreReference = new We.WebExtensionStoreReference()
{
Id = _WebExtensionStoreReferenceId,
Version = _WebExtensionStoreReferenceVersion,
Store = _WebExtensionStoreReferenceStore,
StoreType = _WebExtensionStoreReferenceStoreType
};
We.WebExtensionReferenceList webExtensionReferenceList = new We.WebExtensionReferenceList();
We.WebExtensionPropertyBag webExtensionPropertyBag = new We.WebExtensionPropertyBag();
We.WebExtensionProperty webExtensionProperty = new We.WebExtensionProperty() { Name = "Office.AutoShowTaskpaneWithDocument", Value = "true" };
webExtensionPropertyBag.Append(webExtensionProperty);
We.WebExtensionBindingList webExtensionBindingList = new We.WebExtensionBindingList();
We.Snapshot snapshot = new We.Snapshot();
snapshot.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
webExtension.Append(webExtensionStoreReference);
webExtension.Append(webExtensionReferenceList);
webExtension.Append(webExtensionPropertyBag);
webExtension.Append(webExtensionBindingList);
webExtension.Append(snapshot);
webExtensionPart.WebExtension = webExtension;
//TaskPane
Wetp.Taskpanes taskpanes = new Wetp.Taskpanes();
taskpanes.AddNamespaceDeclaration("wetp", "http://schemas.microsoft.com/office/webextensions/taskpanes/2010/11");
Wetp.WebExtensionTaskpane webExtensionTaskpane = new Wetp.WebExtensionTaskpane()
{
DockState = "left",
Visibility = true,
Width = 320D,
Row = 0U,
Locked = false
};
Wetp.WebExtensionPartReference webExtensionPartReference = new Wetp.WebExtensionPartReference() { Id = "rId1" };
webExtensionPartReference.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
webExtensionTaskpane.Append(webExtensionPartReference);
taskpanes.Append(webExtensionTaskpane);
webExTaskpanesPart.Taskpanes = taskpanes;
}
I set up a folder to serve up the referenced Add-In and it seems to work fine when I run it in my development environment. When I run the same code in my QA environment (different domain and certain settings of course), it seems to find the Add-In manifest because it brings up the TaskPane in Word, but it shows "We can't find the task pane to open. Contact the add-in developer for assistance." The Add-In itself seems to be working because when I add it to the Ribbon and click on the button, the Add-In comes up fine and even works with a Word doc.
I compared the two Word documents that were downloaded in dev and QA environments and except for the location of the Add-In manifest they are pretty much identical. I used Open XML SDK Productivity Tool for Microsoft Office to do the comparison (awesome tool by the way).
I don't have admin rights on the QA domain so can't run any debug tools there. Anyone have any ideas?
Did you also put the name "Office.AutoShowTaskpaneWithDocument" as the TaskPaneId in the Actions section in the manifest file?
<Action xsi:type="ShowTaskpane">
<TaskpaneId>Office.AutoShowTaskpaneWithDocument</TaskpaneId>
<SourceLocation resid="Contoso.Taskpane.Url" />
</Action>

Crm 2011 - How to set a default form depending on attribute value (without using Javascript)?

I have a little requirement that is making me crazy:
We have 8 different forms for the Contact Entity.
We also have a pick list with 8 options.
The idea is that based on the option selected we could open that Contact record showing by default a particular form WITHOUT USING JAVASCRIPT in order to avoid performance problems (each record has to be loaded twice). Example:
Forms:
Form 1
Form 2
Form 3
Pick List Values - Default Form:
Form 1
Form 2
Form 3
If Form 3(pick list value) is selected then, the next time I open that record, Form 3 should be displayed by default.
If Form 1(pick list value) is selected then, the next time I open that record, Form 1 should be displayed by default.
I've trayed registering a plugin at the systemform entity, in RetrieveFilteredForms message, updating the userentityuisettings table and I've been able to set a "DEFAULT" that is displayed every time the records is opened regardless the last opened form.
I've trayed registering a plugin at the contact entity, in Retrieve message, updating the userentityuisettings table but I found that Crm only consults the table Once if there is no attribute updated, the following times Crm take the the default form to open value from the cache.
This is an old question but since it's coming up in my searches for this problem I wanted to add my solution.
We use Dynamics CRM 2013. To my knowledge, later versions of 2011 also support this technique.
The form that is displayed when an entity is opened is determined by a few things - the default form, the security roles and fallback settings for a form and the last form used by the current user for that entity. We had a similar problem to the asker where we wanted a different account form displayed based on the value of a form. We were also tired of the constant reload/refresh that javascript techniques are subject to.
I found some blog posts (in particular this one: http://gonzaloruizcrm.blogspot.com/2014/11/avoiding-form-reload-when-switching-crm.html) which mentioned that it is possible to write a plugin to the Retrieve of the entity that allows you to read out the value (LastViewedFormXml) from UserEntityUISettings that stores which form was last used. If it's not the form you want, you can write in the desired value. This avoids the javascript form refreshing.
I had to modify some code from the samples I found to get it to work, but I'm happy with the results. You need to generate an entity class using CrmSvcUtil and include it in the project. You can get your form guids from the url of the form editor.
using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
namespace CRM.Plugin.AccountFormSwitcher
{
public class Plugin : IPlugin
{
public enum accountType
{
Customer = 100000000,
Vendor = 100000001,
Partner = 100000002,
Other = 100000003
}
public const string CustomerAccountFormId = "00000000-E53C-4DF4-BC99-93856EDD168C";
public const string VendorAccountFormId = "00000000-E49E-4197-AB5E-F353EF0E806E";
public const string PartnerAccountFormId = "00000000-B8C6-4E2B-B84E-729AA11ABE61";
public const string GenericAccountFormId = "00000000-8F42-454E-8E2A-F8196B0419AF";
public const string AccountTypeAttributeName = "cf_accounttype";
public void Execute(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
{
throw new ArgumentNullException("serviceProvider");
}
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
var pluginContext = (IPluginExecutionContext)context;
if (pluginContext.Stage == 20) //pre-operation stage
{
var columns = (ColumnSet)pluginContext.InputParameters["ColumnSet"];
if (!columns.Columns.Contains(AccountTypeAttributeName))
columns.AddColumn(AccountTypeAttributeName);
}
else if (pluginContext.Stage == 40) //post-operation stage
{
EntityReference currentEntity = (EntityReference)context.InputParameters["Target"];
if (currentEntity == null)
return;
var query = new QueryExpression(Account.EntityLogicalName);
query.Criteria.AddCondition("accountid", ConditionOperator.Equal, currentEntity.Id);
query.ColumnSet = new ColumnSet(AccountTypeAttributeName);
var accounts = service.RetrieveMultiple(query).Entities;
Account currentAccount = (Account)accounts[0];
SetForm(currentAccount, service, context.UserId);
}
}
private void SetForm(Account account, IOrganizationService service, Guid userId)
{
var query = new QueryExpression(UserEntityUISettings.EntityLogicalName);
query.Criteria.AddCondition("ownerid", ConditionOperator.Equal, userId);
query.Criteria.AddCondition("objecttypecode", ConditionOperator.Equal, Account.EntityTypeCode);
query.ColumnSet = new ColumnSet("lastviewedformxml");
var settings = service.RetrieveMultiple(query).Entities;
// Some users such as SYSTEM have no UserEntityUISettings, so skip.
if (settings == null || settings.Count != 1 || account.cf_AccountType == null) return;
var setting = settings[0].ToEntity<UserEntityUISettings>();
string formToUse;
switch ((accountType)account.cf_AccountType.Value)
{
case accountType.Customer:
formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", CustomerAccountFormId);
break;
case accountType.Vendor:
formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", VendorAccountFormId);
break;
case accountType.Partner:
formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", PartnerAccountFormId);
break;
case accountType.Other:
formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", GenericAccountFormId);
break;
default:
formToUse = String.Format("<MRUForm><Form Type=\"Main\" Id=\"{0}\" /></MRUForm>", GenericAccountFormId);
return;
}
// Only update if the last viewed form is not the one required for the given opportunity type
if (!formToUse.Equals(setting.LastViewedFormXml, StringComparison.InvariantCultureIgnoreCase))
{
var s = new UserEntityUISettings { Id = setting.Id, LastViewedFormXml = formToUse };
service.Update(s);
}
}
}
}
And to address the asker's issue with it only consulting the UserEntityUISettings once, I'm not sure why that's happening. But why not use javascript to change the form when the triggering attribute is changed? That what I do and I haven't ran into any problems with the plugin not displaying the desired for.
EDIT: the OP specified after that he needs a solution without javascript, I leave this reply for future references.
You can use javascript, inside the OnLoad event you check the picklist value and navigate to the desired form. Check this code as example
var value = Xrm.Page.getAttribute("new_optionset").getValue();
switch(value) {
case 100000000:
Xrm.Page.ui.formSelector.items.get(0).navigate();
break;
case 100000001:
Xrm.Page.ui.formSelector.items.get(1).navigate();
break;
case 100000002:
Xrm.Page.ui.formSelector.items.get(2).navigate();
break;
/// ... other cases here
default:
// default form to open when there is no value
Xrm.Page.ui.formSelector.items.get(0).navigate();
}
This is an oldy but a goody... I use CRM Rules to generate Hide Tab and Show Tab actions that essentially show each user role a different form.
Steps:
Create one, massive form with all of the fields you want to display (if you already have many forms, this would include all fields across all forms).
Organize the form into TABS, with each tab showing 'one form' worth of data. (You can also have many TABS for each user group). Typically, I create one 'General' tab that has the key option set that will set the rest of the form up, and any fields that are common across roles / user groups / forms, like status, name, etc...
3) Hide all of the tabs except the General tab by unchecking the visible box on those tab form property forms in the Admin UI.
4) Using CRM Rules (crm-rules.com), you can then bring in the metadata, with the form, and all of the tabs and sections in there. Then you just have to write one rule for each 'form' you are trying to show... Each rule is of this format:
IF User_Role contains 'Sales' THEN Show Tab: Sales
IF User_Role contains 'Marketing' THEN Show Tab: Marketing
You can also do this, of course, with an option set, or any field on the form as the condition... One of the benefits of this approach is that if users cross role boundaries (or some users were part of security roles that could access multiple forms), this technique shows them both forms at once...
HTH somebody, CRM Rules (www.crm-rules.com) generates the JavaScript to make this happen...

Crystal Reports Runtime & Redistributable

Is there a difference between these two things. I am trying to move some reports from a local server to a dev server and I know that we have installed the redist on the dev server, but am still having problems getting the report to run. Is the runtime separate I come accross different sites mentioning both things but havent been able to tell if they are talking about the same thing
*Edit - posting code to see if as dotjoe suggested I have incorrectly labled my report path. the database connection is returned from a method to a string array reportString so that is what that array is.
<CR:CrystalReportViewer ID="CrystalReportViewer2" runat="server"
AutoDataBind="True" Height="50px" Width="350px" ReuseParameterValuesOnRefresh="True" ToolbarImagesFolderUrl="~/images/reportViwerImages"/>
ConnectionInfo myConnectionInfo = new ConnectionInfo();
myConnectionInfo.ServerName = reportString[1];
myConnectionInfo.DatabaseName = reportString[0];
myConnectionInfo.UserID = reportString[2];
myConnectionInfo.Password = reportString[3];
string ReportPath = Server.MapPath("../../mdReports/CrystalReport.rpt");
CrystalReportViewer2.ReportSource = ReportPath;
ParameterField field1 = new ParameterField();
ParameterDiscreteValue val1 = new ParameterDiscreteValue();
val1.Value = hiddenFieldReportNumber.ToString();
field1.CurrentValues.Add(val1);
SetDBLogonForReport(myConnectionInfo);
private void SetDBLogonForReport(ConnectionInfo myConnectionInfo)
{
TableLogOnInfos myTableLogOnInfos = CrystalReportViewer2.LogOnInfo;
foreach (TableLogOnInfo myTableLogOnInfo in myTableLogOnInfos)
{
myTableLogOnInfo.ConnectionInfo = myConnectionInfo;
}
}
you have not load the report from the given Path.
Please see below link

ContactsContract.RawContacts.SYNC2 is always null on real device, works fine on SDK emulator

I'm writing a SyncProvider based on Sam Steele's demo.
However, I ran into a major problem. I write timestamps into the ContactsContract.RawContacts.SYNC2 field. On the SDK emulator, this works just fine. On my Galaxy Nexus, however, it doesn't... Does anyone know why or how to fix that?
Here's my code:
Writing the timestamp:
builder = ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI);
builder.withSelection(ContactsContract.RawContacts.CONTACT_ID + " = '" + rawContactId + "'", null);
builder.withValue(ContactsContract.RawContacts.SYNC2, String.valueOf(timestamp));
operationList.add(builder.build());
mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
Reading it out:
Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon()
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type)
.build();
mContentResolver = context.getContentResolver();
Cursor c1 = mContentResolver.query(rawContactUri, new String[] { BaseColumns._ID, UsernameColumn, ContactsContract.RawContacts.SYNC2 }, null, null, null);
while (c1.moveToNext()) {
SyncEntry entry = new SyncEntry();
entry.raw_id = c1.getLong(c1.getColumnIndex(BaseColumns._ID));
long oldTimestamp = -1;
if (!c1.isNull(c1.getColumnIndex(ContactsContract.RawContacts.SYNC2))){
oldTimestamp = Long.valueOf(c1.getString(c1.getColumnIndex(ContactsContract.RawContacts.SYNC2)));
Log.i("READ TIMESTAMP", String.valueOf(oldTimestamp));
}
entry.photo_timestamp = oldTimestamp;
localContacts.put(c1.getString(1), entry);
}
c1.close();
For some reason, c1.isNull always seems to be true on the Galaxy Nexus. What am I doing wrong?
UPDATE: Apparently, it sometimes gets written for a few contacts (1-5 out of >100), so I'm even more confused now...
UPDATE: I've checked the ContactProvider SQL db and the sync2 field really is empty, so it seems to be a problem with how I'm writing the timestamp.

Something wrong with my socket program

I wrote a program communicated with sockets.But I don't know why they don't work.
Server Code:
this.serverSocket = new ServerSocket(ServerConnector.port);
this.socketListener = this.serverSocket.accept();
System.out.println(this.socketListener.getPort());
this.objIn = new ObjectInputStream(this.socketListener.getInputStream());
System.out.println("1");
this.objOut = new ObjectOutputStream(this.socketListener.getOutputStream());
System.out.println("1");
this.objOut.writeInt(19999);
System.out.println("1");
this.objOut.writeObject(new Date());
System.out.println("1");
Client Code:
this.clientSocket = new Socket(ClientConnector.host, ClientConnector.port);
System.out.println(this.clientSocket.getPort());
this.objIn = new ObjectInputStream(this.clientSocket.getInputStream());
System.out.println("1");
this.objOut = new ObjectOutputStream(this.clientSocket.getOutputStream());
System.out.println("1");
int i = (Integer) this.objIn.readInt();
System.out.println(i);
Date date = (Date) this.objIn.readObject();
The truth is, they don't show any information I suggested to pass through(19999 and date), they even can't print a line of "1"(I added for testing). It means even the line below can't work normally. I really confused by these, who can figure the error out?
this.objIn = new ObjectInputStream(this.clientSocket.getInputStream());
You are most likely experiencing the effect of Nagle's Algorithm. which tries to optimize packet sending in TCP. If you want to send your data immediately you need to disable it using the setTcpNoDelay method on the socket interface.
P.S. no idea why the question is tag'ed as osgi, as it has no relevance to OSGi at all.