Crm2011 用Htm Webresource添加另外一个实体的信息到当前实体

之前接手这个项目的时候,看到的设计是这样的:

实体A的页面上有一个Lookup,连到实体B;

实体B的所有Fields都要展示到实体A;

实体A不能改动这些Fields;

实体B改动了这些Fields,也要体现到实体A;

在实体A重复创建和实体B一模一样的Fields……

这样的设计非常无聊,既然实体A要展示那些Fields,又不能改,其实只要直接拿实体B的信息即可,不需要重复创建Fields。

但是他们这样做是有原因的,因为CRM的sub grid展示形式很单一,无法达到用户的需要。

于是,现在,我改成了用Htm Web Resource来实现。

如图:

上图中的红框的信息全是来自“Property”这个Lookup的实体。

实现方法如下:

1. 创建一个Css,用来控制样式保持和CRM一致。我这里的名字是master.css,上传到CRM,(new_/Styles/master.css)

body { font-family:Tahoma; font-size:11px; color:393839; margin:0px; background-color:F6F8FA; border:0px; }
table
{font-size:11px;}
td
{padding: 5px 10px 3px 0px;}
h3
{font-size:12px;}

2. 上传sdk里的jquery到CRM(new_/Scripts/jquery1.4.1.min.js), jquery库可以在sdk找到:sdk\samplecode\js\restendpoint\jqueryrestdataoperations\jqueryrestdataoperations\scripts\jquery1.4.1.min.js

3. 创建Htm页面,上传到CRM(new_/PropertyInfo.htm),这里我省略部分方法只是重复的代码,大家要根据需要修改:

<HTML><HEAD><TITLE></TITLE> 
<SCRIPT src="../ClientGlobalContext.js.aspx"></SCRIPT>
<SCRIPT type=text/javascript src="Scripts/jquery1.4.1.min.js"></SCRIPT>
<SCRIPT type=text/javascript src="Scripts/sdk.metadata.js"></SCRIPT>
<LINK rel=stylesheet type=text/css href="Styles/master.css"></LINK>
<SCRIPT language=javascript>

var _serverUrl;
function retrievePropertyInfo() {

var customerAttribute = parent.Xrm.Page.data.entity.attributes.get("new_property");


if (customerAttribute != null) {


customerValue
= customerAttribute.getValue();


if (customerValue != null && customerValue[0] != null) {
var customerType = customerValue[0].typename;
var customerId = customerValue[0].id;
return retrieveRecord(customerId, "new_propertySet", retrieveCompleted, null);


}
}
}


function retrieveRecord(id, odataSetName, successCallback, errorCallback) {
var context = GetGlobalContext();
var serverUrl = context.getServerUrl();
_serverUrl
= serverUrl;

var odataEndPoint = "/XRMServices/2011/OrganizationData.svc";


if (!id) {
alert(
"record id is required.");
return;
}


if (!odataSetName) {
alert(
"odataSetName is required.");
return;
}


$.ajax({
type:
"GET",
contentType:
"application/json; charset=utf-8",
datatype:
"json",

url: serverUrl
+ odataEndPoint + "/" + odataSetName + "(guid'" + id + "')",
beforeSend:
function (XMLHttpRequest) {

XMLHttpRequest.setRequestHeader(
"Accept", "application/json");
},
success:
function (data, textStatus, XmlHttpRequest) {
if (successCallback) {
successCallback(data.d, textStatus, XmlHttpRequest);
}
},
error:
function (XmlHttpRequest, textStatus, errorThrown) {
if (errorCallback)
errorCallback(XmlHttpRequest, textStatus, errorThrown);
else
errorHandler(XmlHttpRequest, textStatus, errorThrown);
}
});
}


function retrieveCompleted(data, textStatus, XmlHttpRequest) {
/*Display the required fields and hide if the fields are null */
var entity = data;
    
//Picklist
var Type = (entity.new_Type.Value == null) ? "" : RetrieveOptionsetLabel("new_property", "new_type", entity.new_Type.Value, "type");
//Text
var AddressLine1 = (entity.new_AddressLine1 == null) ? "" : entity.new_AddressLine1;

if (addressline1 != "") {
document.getElementById(
"addressline1").innerHTML = AddressLine1;

}
//Hyperlink
var PortfolioName = (entity.new_Portfolio.Name == null) ? "" : entity.new_Portfolio.Name;
var PortfolioId = (entity.new_Portfolio.Id == null) ? "" : entity.new_Portfolio.Id;
if (portfolio != "") {
document.getElementById(
"portfolio").innerHTML =
"<a href='" + _serverUrl + "/main.aspx?etc=10014&id=%7b" + PortfolioId + "%7d&pagetype=entityrecord' target=_blank>" + PortfolioName + "</a>";


}




}


function RetrieveOptionsetLabel(entityName, optionSetName, optionSetValue, attributeId) {
// Entity schema name
var entityLogicalName = entityName;
// option set schema name
var RetrieveAttributeName = optionSetName;
// Target Field schema name to which optionset text needs to be assigned
var AssignAttributeName = attributeId;

// Option set value for which label needs to be retrieved
var stateValue = optionSetValue;

// Calling Metadata service to get Optionset Label
SDK.MetaData.RetrieveEntityAsync(SDK.MetaData.EntityFilters.Attributes,
entityLogicalName,
null,
false,
function (entityMetadata) {
successRetrieveEntity(entityLogicalName, entityMetadata, RetrieveAttributeName, stateValue, AssignAttributeName);
},
errorDisplay);


}

// Called upon successful metadata retrieval of the entity
function successRetrieveEntity(logicalName, entityMetadata, RetrieveAttributeName, OptionValue, AssignAttributeName) {
///<summary>
/// Retrieves attributes for the entity
///</summary>

var success = false;
for (var i = 0; i < entityMetadata.Attributes.length; i++) {
var AttributeMetadata = entityMetadata.Attributes[i];
if (success) break;
if (AttributeMetadata.SchemaName.toLowerCase() == RetrieveAttributeName.toLowerCase()) {
for (var o = 0; o < AttributeMetadata.OptionSet.Options.length; o++) {
var option = AttributeMetadata.OptionSet.Options[o];
if (option.OptionMetadata.Value == OptionValue) {
document.getElementById(AssignAttributeName).innerHTML
= option.OptionMetadata.Label.UserLocalizedLabel.Label;
success
= true;

break;
}
}
}

}


}

function errorDisplay(XmlHttpRequest, textStatus, errorThrown) {

alert(errorThrown);
}

</SCRIPT>


<META charset=utf-8></HEAD>
<BODY onload=retrievePropertyInfo() contentEditable=false>
<div id=propertyinfo>
<table style="100%">

<tbody>

<tr>
<td style="8%">Address Line 1</td>
<td id="addressline1" style="18%"></td>
<td style="8%">Type</td>
<td id="type" style="18%"></td>

<td style="8%">Asset ID</td>
<td id="assetid" style="18%"></td>
<td style="8%">Country</td>
<td id="country" style="auto"></td>

</tr>
<tr>
<td>Address Line 2</td>
<td id="addressline2"></td>


<td>Property Type</td>
<td id="propertytype"></td>

<td>Portfolio</td>
<td id="portfolio"></td>
<td>State/Province</td>
<td id="state"></td>
</tr>

<tr>

<td>Address Line 3</td>
<td id="addressline3"></td>
<td>Property SubType</td>
<td id="propertysubtype"></td>



<td>County</td>
<td id="county"></td>
<td>City</td>
<td id="city"></td>
</tr>

</tbody>
</table>
</div>

</BODY></HTML>


4. 将这个Htm Webresource插入我们需要它的地方,这样就可以了。

注意,我们的property lookup必须要在页面上才可以,设为不可见也行,因为如果它不在页面上,我们就拿不到它的id了,当然,通过别的方法拿到也是可以,但是就增加了不必要的麻烦。

补充,我们这里是用odata来取得数据的,写odata query的时候要注意。我是觉得很讨厌写这个query,所以我是用这个工具的:CRM 2011 OData Query Designer

如果我们是取一个实体的数据(
http://XXXX:8080/OOOOO/xrmservices/2011/OrganizationData.svc/odataSetName (guid'3653C6D5-2077-E111-920A-000C29139AA1')),那么返回的肯定是一个实体,则我们分析数据的时候只要用类似entity.fieldname 就可以拿到相应的值。

如果我们取得是多个实体的数据(http://XXXX:8080/OOOOO/xrmservices/2011/OrganizationData.svc/odataSetName?$select=new_Field1Name,new_new_entityB_new_entityA_entityBName/new_Field2Name$expand=new_new_entityB_new_entityA_entityBName&$filter=new_entityAId eq guid'3653C6D5-2077-E111-920A-000C29139AA1'),那么返回的是一个数组,我们分析数据的时候,对于a的数据要这样entity.results[0].field1name;对于b的数据则是:entity.results[0].new_new_entityB_new_entityA_entityBName.field2name

再补充:

如果取得是数据是Date,需要进行一下转换,odata返回的Date是这样的Date(1235764800000)

这样转换:

function ConvertTime(date) {
//This function use for convert the Date value get from odata, convert to javascript readable value
if (date == "") {
return "";
}
else {
var utcTime = parseInt(date.substr(6)); //date is like Date(1235764800000)
var result = new Date(utcTime);
result.setHours(result.getHours() + 8); //Database time is 8 hours late before local time
return result.format("M/dd/yyyy");
}
}


好的,基本上就是这样。


原文地址:https://www.cnblogs.com/nixjojo/p/2421386.html