6

내 사이트 모음에서 소수의 목록에 사용 된 사이트 콘텐츠 형식이 있습니다. 그 콘텐츠 유형에서 ItemAdding 이벤트를 처리 할 이벤트 수신기를 설명합니다. 이것은 잘 작동합니다. 이제 ItemUpdating도 처리 할 수 ​​있도록 컨텐트 유형을 업데이트해야합니다. OTTOMH, 간편한 버전 추적을 허용하는 것처럼 보였으므로 콘텐츠 형식에 대한 XML을 수정하기 만했습니다. 이는 내 업데이트가 사이트 콘텐츠 형식에 적용되었지만이 콘텐츠 형식을 사용하고 있던 목록에는 적용되지 않았다는 점에서 효과가있었습니다. 이것은 많은 것이 예상되었습니다. 설치 이 있고 그 내용 유형을 활성화 한 후 어떠한 경우에도이미 배포 된 SharePoint 콘텐츠 형식을 업데이트하여 추가 항목 이벤트 처리

당신이 콘텐츠 유형에 대한 콘텐츠 형식 정의 파일을 업데이트 한다 : 그럼는 SharePoint SDK가의 grim view 걸리는 것으로 나타났습니다. Windows SharePoint Services는 내용의 변경 내용을 추적하지 않습니다. 형식 정의 파일. 따라서 에는 사이트 콘텐츠 형식에 대한 변경 내용을 자식 콘텐츠 형식 인 으로 푸시 다운 할 수있는 방법이 없습니다.

SDK는 UI 또는 코드를 사용하여 변경 내용을 푸는 방법을 설명하는 몇 개의 섹션을 가리 킵니다. UI는 이벤트 수신기에 훅을 제공하지 않으므로 코드 경로를 선택하게 될 것입니다.

는 내가 같은 것을 할 그냥 콘텐츠 형식의 목록의 사본에 새 이벤트 수신기를 추가 할 수있을 거라고 생각 :

SPList list = web.Lists["My list"]; 
SPContentType ctype = list.ContentTypes["My content type"]; 
// Doesn't work -- EventReceivers is null below. 
ctype.EventReceivers.Add(SPEventReceiverType.ItemUpdating, 
         "My assembly name", "My class name"); 

그러나 캐치 ctype.EventReceivers 여기 널이다 , 비록 내가이 목록에 이미 매달린 ItemAdding을 가지고있다. 그것이 목록 자체로 옮겨진 것 같습니다. 따라서 목록에는 유효한 EventReceivers 컬렉션이 있습니다.

  1. 단지 목록에 직접 새 이벤트 수신기를 추가하고 내 콘텐츠를 모두 입력에 대해 잊지이 작업을 수행하는 올바른 방법은 다음과 같습니다

    SPList list = web.Lists["My list"]; 
    list.EventReceivers.Add(SPEventReceiverType.ItemUpdating, 
             "My assembly name", "My class name"); 
    

    그래서, 나는 몇 가지 질문이?

  2. 이 변경을 수행하려면 구성 관리와 관련하여이를 처리하는 가장 좋은 방법은 무엇입니까? 모든 적절한 목록을 찾고 각각을 수정하기 위해 간단한 콘솔 앱을 만들어야합니까? 아니면 어떤면에서 더 나은 옵션을 만드는 것입니까? 어느 쪽이든,이 변화는 독자적으로 진행될 것이고이 컨텐츠 유형으로 작업해야하는 미래의 개발자들에 의해 발견되기 어려울 것 같습니다.
+0

좋은 질문 : 비슷한 것을 묻는 의미였습니다. –

답변

2

EventReceiver를 추가 한 후 ctype.Update (true)를 호출 했습니까? 그렇지 않으면 지속되지 않을 것입니다. 목록 콘텐츠 형식을 사용하지 말고 대신 SPWeb.ContentTypes를 사용하십시오.

이 코드는 나를 위해 작동 :

var docCt = web.ContentTypes[new SPContentTypeId("0x0101003A3AF5E5C6B4479191B58E78A333B28D")]; 
//while(docCt.EventReceivers.Count > 0) 
// docCt.EventReceivers[docCt.EventReceivers.Count - 1].Delete(); 
docCt.EventReceivers.Add(SPEventReceiverType.ItemUpdated, "ASSEMBLYNAME, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c5b857a999fb347e", "CLASSNAME"); 

docCt.Update(true); 

진정한 매개 변수는이뿐만 아니라 모든 자식 ContentTypes에 푸시 다운됩니다 것을 의미합니다. (즉, 콘텐츠 유형을 사용하는 모든 목록에).

+0

SDK가 콘텐츠 형식 정의를 변경하지 않았다는 사실을 암시 한 후에도 그 길을 간다. 이제는 변경 사항을 푸시하도록 명시 적으로 말할 수 있기 때문에 이것이 다르다는 것을 알았습니다. 이것은 그것을하는 완벽한 방법처럼 보입니다. 나는 그것을 밖으로 시도 할 것이다. 감사! 자, 어떻게 구성 관리 측면에서 이것을합니까? :) –

+0

CType def를 건드리지 않아야한다는 것은 사실입니다. 그러나 그것은 단지 그것을 만드는 데 사용 된 CAML을 의미합니다/당신이 좋아하는 것을 할 수있는 객체 모델을 통해. 위의 코드는 cType 정의를 보유하는 기능과 결합 된 기능 수신자를 통해 실행됩니다. while ... delete가 추가되어 원하는만큼 여러 번 기능을 비활성화/활성화 할 수 있으며 항상 cType 당 1 개의 이벤트 수신자를 유지합니다 (IMHO는 가장 깨끗한 방법입니다). 질문에 대한 답변이 있으십니까? – Colin

0

질문의 두 번째 부분까지 나는 과거와 비슷한 상황에서 우리가 한 일을 전하고 싶었습니다.우리 상황에서는 두 가지 다른 스크립트가 필요했습니다. 하나는 모든 웹의 모든 목록으로 콘텐츠 유형 업데이트를 전파 할 수있는 사이트이고 다른 하나는 마스터 페이지/페이지 레이아웃을 사이트 정의 (사용자 정의되지 않은 양식).

그래서 각 작업에 대해 몇 가지 사용자 정의 stsadm 명령을 만들었습니다. 스크립트를 소스 제어에 배치 할 수 있고 이미 존재하는 stsadm 인터페이스를 구현하기 때문에이 방법을 사용하는 것이 좋습니다.

Custom SharePoint stsadm Commands

1

귀하의 질문의 두 번째 부분에 대답하기 위해, 때문에에 contenttypes에 변경 사실이 까다로운 일이 sitecollection 이뤄져 사용 오기 '목록에 푸시 다운 할. "복사"는 기본적으로 sitecollection의 필드로 이루어지며 목록에 contenttype을 추가 한 후에는 더 이상 연결이 없습니다. 이것은 sitecollection에 영향을주지 않으면 서 목록을 변경해야한다는 사실 때문이라고 생각합니다. 어쨌든이 "문제"에 대한 저의 기여와 그것을 해결 한 방법은 XML을 "마스터"로 만드는 것과 featurereceiver에서 XML을 끌어다 놓고 contenttype이 사용되는 모든 장소를 찾고 거기에서 contenttypes (실제로 fieldrefs)를 목록 수준에서 XML의 것과 일치시킵니다.

var elementdefinitions = properties.Feature.Definition.GetElementDefinitions(); 

foreach (SPElementDefinition elementDefinition in elementdefinitions) 
{ 
    if (elementDefinition.ElementType == "ContentType") 
    { 
    XmlNode ElementXML = elementDefinition.XmlDefinition; 

    // get all fieldrefs nodes in xml 
    XmlNodeList FieldRefs = ElementXML.ChildNodes[0].ChildNodes; 

    // get reference to contenttype 
    string ContentTypeID = ElementXML.Attributes["ID"].Value.ToString(); 
    SPContentType ContentType = 
     site.ContentTypes[new SPContentTypeId(ContentTypeID)]; 

    // Get all all places where the content type beeing used 
    IList<SPContentTypeUsage> ContentTypeUsages = 
     SPContentTypeUsage.GetUsages(ContentType); 
    } 
} 

다음 일은이 (ID 속성에 의해 수행) 목록과 동일한 것을 확인에있는 필드와 XML을 XML로 fieldrefs를 비교하는 것입니다 : 코드는 같은 간다. 불행히도 우리는 SPFieldLink 클래스 (fieldref)에서 모든 것을 업데이트 할 수 없으며 여기서 지원하지 않습니다. 실제로이 값들을 업데이트하기 위해 (f.e. ShowInEditForm) 업데이트했습니다.

+0

코드 조각이 좋지만 itemeventreceiver를 추가하는 것과는 완전히 관련이 없습니다. +1 – Colin

+0

@Colin - 아니요, 콘텐츠 유형에 대한 변경 사항을 업데이트하는 것과 관련이 있습니다. 이벤트 리시버의 추가는 이미 내 생각에 응답되었습니다. –