แก้ปัญหา SmartObjects สร้างข้อมูลซ้ำ

มาจากคำถามจากทางบ้านอีกเช่นกันครับ สำหรับปัญหาที่ว่าสร้างข้อมูลจาก SmartObjects แล้วพบว่ามีข้อมูลเข้าไป 2 records

ถ้าใครเจอปัญหานี้เหมือนกันให้ลองตรวจสอบว่าเราได้ตั้งค่าหรือมีอาการตามนี้หรือไม่

  1. SmartObjects ต่อกับ Stored procedure ใน SQL
  2. Method ใน SmartObjects ที่ใช้สร้างข้อมูลเป็น type แบบ List
  3. ทดสอบเรียกผ่าน SmartObjects Services Tester แล้วพบว่าสร้าง 1 record แต่ถ้าเรียกผ่าน SmartForm แล้วเข้าไป 2 records

methodList.png

ถ้าใครเจอว่ามีอาการดังกล่าว แสดงว่าน่าจะมาจากสาเหตุเดียวกันแล้วครับ ให้ลองตรวจสอบเพิ่มอีกครับว่าเราได้ไปเปิดการแสดงผล paging ใน List View ด้วยหรือไม่

วิธีตรวจสอบง่าย ๆ คือไปเปิด List View ขึ้นมานะ ว่ามีแสดง paging หน้าสุดท้ายหรือไม่ (ถ้าไม่ได้เปิดจะไม่มีในวงเล็บ) แต่ถ้ามีก็ชัดเลยครับ ไปอ่านวิธีแก้กันต่อด้านล่างได้เลย (ส่วนวิธีการเปิดเคยเขียนไว้ใน blog นี้ -> ว่าด้วยเรื่องการแสดง Paging ใน Listview)

listview3.png

สาเหตุของอาการนี้มีสองอย่างด้วยกัน คือเพราะ method ใน SmartObject เป็นแบบ List และมีการเปิด SmartObject.RuntimeListViewRowCount ไว้ ทำให้ทุก method ที่เป็น List จะถูกเรียกสองครั้งเสมอ

วิธีแก้มีสองวิธีครับ

  1. แบบง่าย: ก็คือไปปิดการแสดง paging ของ List View ซะ (SmartObject.RuntimeListViewRowCount = false) แต่ถ้าเรายังอยากได้ทั้งการแสดงผลแบบนี้ และยังสร้าง record ให้ไม่ซ้ำด้วย ไปทำตามข้อสองครับ
  2. แบบยาก: ต้นเหตุคือตัว stored procedure ส่งประเภท method มาเป็น List อยู่ เราต้องไปแก้ stored procedure ให้ส่งมาเป็นประเภท Execute แทน โดยการเพิ่มบรรทัด SET FMTONLY ON ใน stored procedure แนะนำให้อ่านวิธีแก้เต็ม ๆ ใน KB นี้ครับ -> Determined SmartObject method ‘List’ or ‘Execute’ when SmartObject was created from SQL Store Procedure

ST136024.jpg

Advertisements

ย้อน version ของ K2 component ยังไงกันนะ?

Blog นี้เริ่มจากคำถามจากทางบ้านนะครับ ว่าในการพัฒนา K2 เห็นมีการเก็บ version ไว้ ทั้ง Workflow , SmartForm และ SmartObject

version.png

แต่ยังหาวิธีการย้อน version ไม่เจอว่าต้องทำยังไง ใน blog นี้เลยจะบอกวิิธีการของแต่ละส่วนครับ

1. Workflow

เริ่มด้วยการย้อน version ของ workflow ก่อนนะครับ เพราะเป็นส่วนที่ทำได้ง่ายที่สุดแล้ว เราสามารถเข้าไปดู version ของ workflow ได้ผ่านทาง K2 Workspace หรือ K2 Management (สำหรับ version 4.7 ขึ้นไป)

สำหรับ K2 Workspace ไปที่เมนู [Server name] -> Workflow Server -> Processes -> [Process Name] -> Versions

processVersion.png

สำหรับ K2 Management ไปที่ Workflow Server -> [Workflow name] แล้วกดที่ tab Versions

processVersion47

โดยในทั้งสองไซต์ เราสามารถเลือกย้อน version ในการทำงานของ workflow ได้โดยเลือกกดที่ Set as default (มีผลเฉพาะกับ workflow ที่ยังไม่ start มานะครับ) และสามารถเลือก Download workflow version นั้น มาแก้ไขได้อีกด้วย

2. SmartForm

การย้อน version ของ smartform สามารถทำได้โดยใช้ stored procedure ที่ชื่อ Form.mRevertToVersion โดยสามารถย้อนได้ทั้ง View และ Form

สามารถตามไปอ่านวิธีการ step by step ได้ที่ -> How to roll back to a deleted or previous version of a View or a Form

3. SmartObjects

SmartObject นั้นเก็บโครงสร้างอยู่ที่ database ของ K2 แยกตาม version ที่ deploy ไป ดังนั้นการย้อน version SmartObject นั้นต้องทำตรงที่ database เลย โดยไม่ได้มี stored procedure ช่วย เหมือนการย้อน SmartForm

วิธีการทำก็คือ ต้องใช้ SQL Command ในการ update โดยนำ XML ใน SmartObjectXML ของ version ที่ต้องการย้อนกลับไป นำมาอัพเดทให้ version ล่าสุดนั่นเอง

smoVersion.png

ย้อน version SmartForm กับ SmartObject เป็นการทำงานตรงกับ database ของ K2 ซึ่งอาจมีโอกาสเกิดความผิดพลาดกับ database แนะนำว่าไม่ควรทำบนเครื่อง Production และให้ backup database K2 ทั้งก้อน ก่อนจะเริ่มทำนะครับ

การสร้าง Custom Worklist แบบ Step by step (No coding)

การใช้งาน K2 กับ Worklist เป็นของคู่กันมานานนม ตั้งแต่สมัยใช้งานบน workspace จนมาถึงปัจจุบันก็มี worklist control ใน SmartForms ให้ใช้

โดยปกติ worklist control มี field ที่เกี่ยวกับการทำงานของ workflow เช่น Folio, Activity Name, Task Start Date และอื่น ๆ ให้เลือกแสดงได้อยู่แล้ว ซึ่งการใช้งานจริงเรามักอยากได้ worklist ที่มีข้อมูล ของระบบนั้นมาแสดงด้วย โดยทางออกที่เรามักจะทำกันคือการใส่ค่าแปะไว้ใน folio ของ workflow บางที Folio มันก็จะยาว ๆ หน่อยอ่ะนะ (- -“)

Leave00.png

แต่ในวันนี้มานำเสนออีกช่องทางครับ เป็นวิธีการทำ worklist ที่สามารถดึงข้อมูลระบบอื่นมาแสดงด้วย ในตัวอย่างจะเป็น worklist ของ ระบบ Leave request โดยจะมีข้อมูลประเภทการลา วันที่เริ่มลาจนถึงวันที่สิ้นสุด มาแสดงใน worklist ได้ด้วย ผลลัพท์ได้มีหน้าตาตามนี้ครับ

Leave11.png

สิ่งที่ใช้ในการทำ: Worklist Service Broker, Composite SmartObjects

Step by step

  1. ติดตั้ง Worklist Service Broker (ตามไป download ได้ตามลิ้งค์ด้านบนครับ)
    • WorklistService
  2. เพิ่ม field ProcessInstanceID ในตาราง leave request (ใน workflow เพิ่ม SmartObjects Event ให้ไป update ค่า ProcessInstanceID หลังจากส่งงานเข้า workflow ไปแล้วด้วย)
    •  Leave-table
  3. สร้าง composite SmartObject เชื่อมกันระหว่าง Leave Request  และ WorklistService
    • เปิด K2 Studio, สร้าง SmartObject ตั้งชื่อ LeaveRequestWorklist
    • Leave1.png
    • กด Add Method, เลือก Run the wizard in Advance Mode แล้ว กด Next
    • Leave6.png
    • ตั้งชื่อ method ว่า Get Leave Request Worklist แล้วกด Next
    • Leave3.png
    • ในหน้า Configure Method Parameter กด Next (ไม่ต้องสร้าง parameter)
    • ในหน้า Service Method Object กด Add
    • Leave13.png
    • ในหน้า Add Service Method กด Add เลือกไปที่ Service Object Server -> [SQL Service Instance Name] -> Table -> Leave Request -> List
    • Leave4.png
    • กด Create All เพื่อสร้าง properties แล้วกด OK
    • Leave3.png
    • โปรแกรมจะกลับมาที่หน้า Service Method Object กด Add อีกครั้ง
    • Leave12.png
    • ในหน้า Add Service Method กด Add เลือกไปที่ Service Object Server -> Worklist Server -> Basic Worklist Item -> Get Worklist Items
    • Leave7.png
    • กด Create All เพื่อสร้าง properties แล้วกด OK
    • กด Next
    • ในหน้า Setup Service Method Link กด Add
    • Leave9.png
    • ในหน้า Add Service Method Link เลือกปรับค่าดังนี้
      • Service Object Method: Leave Request.List
      • Link Type: Matching Value in both objects
      • Service Object Method: Worklist Service.GetWorklistItems
    • ในส่วนของ Property Name เลือกไปที่ ProcessInstanceID แล้วกด Assign เลือกไปที่ Process InstanceID ตามรูป
    • Leave10.png
    • กด OK
    • กด Next, กด Finish
    • Deploy SmartObjects
  4. ทดสอบและนำ SmartObjects ไปสร้าง ListView, form ต่อเพื่อใช้งาน
    • ตอนเรียกใช้งานก็เรียกผ่าน method ที่เราสร้างขึ้นครับ มันจะได้เฉพาะงานจาก worklist เท่านั้น แล้วจะไป join กับ field จากตาราง Leave Request
    • Field ที่ใช้ฝั่งของ worklist จะมีดังนี้ครับ
      • Link: เป็น URL ที่ส่งมาจาก workflow สำหรับเปิดหน้าฟอร์มเข้าไปอนุมัติ
      • Folio: ชื่อ folio ของ workflow นั้น ๆ
    • Leave11

 

สรุปข้อดีของการทำ custom worklist

  • เพิ่ม field จากฐานข้อมูลมาแสดงผลได้
  • สามารถใช้ฟังก์ชั่นของ list view ได้ เช่น การ sorting, filter, paging

แต่ก็มีข้อจำกัดของการทำ custom worklist นะ

  • ไม่สามารถใช้ function ที่ติดมากับ worklist control ได้ เช่น  Redirect, Delegate, Out of office (ทำได้แต่ต้องเขียนเพิ่มเอง)
  • ต้องสร้าง SmartObjects และ form แยกสำหรับแต่ละระบบ

 

การสร้าง custom worklist ขั้นตอนก็มีดังที่กล่าวไปข้างต้น รวมถึงมีทั้งข้อดีข้อเสีย ทั้งนี้ขอให้เลืิอกนำไปใช้ให้เหมาะสมกับงานของเราครับ 🙂

[K2 SmartForms] – Using Field Property

สวัสดีครับ หายไปนานกับ blog ของ K2 Ranger พอดีวันนี้มีคำถามเข้ามาทาง page K2 Thailand เกี่ยวกับการเลือก field ที่ผูกกับ data source เลยเอามาเขียนให้อ่านกัน

ในส่วนแรกให้เราสร้าง property field เพิ่มใน file .cs

public string Field

{

get

{

return base.GetOption<string>(“Field”, string.Empty);

}

set

{

base.SetOption<string>(“Field”, value, string.Empty);

}

}

จากนั้นก็ไปเพิ่ม property ใน file definition.xml ของ control

<Prop ID=”Field” mappable=”false” friendlyname=”Field” category=”Detail” refreshdisplay=”false” type=”complex” InitializeServerControl=”initializeFieldPropertyConfig” ClearServerControl=”clearFieldConfig” ServerControl=”SourceCode.Forms.Controls.Web.FieldConfiguration.FieldPropertyConfig,SourceCode.Forms.Controls.Web” />

เพิ่มแล้วเรียบร้อยให้ลอง build แล้ว deploy ใหม่ดู เราก็จะสามารถดึง field ที่อยู่ใน SmartObject ที่ผูกกับ view นี้ออกมาได้

Field

FieldSelection

จะมองเห็นเฉพาะ field type ที่ control นี้สามารถใช้งานได้ด้วย

   ส่วนวิธีเอาค่าจาก Field property ไปใช้ต่อ ก็ใช้วิธีเดียวกันกับการดึงค่าใน property อื่นๆ ไปใช้นะครับ สำหรับรอบนี้ขอลาไปเท่านี้ครับ 🙂

 

[K2 SmartForms] – Can’t click OK to finish rule in designer

สวัสดีครับ หลายๆ คนคงเคยเจอปัญหาอยู่บ้าง เวลาเราใส่ action เข้าไปใน SmartForms เยอะๆ จะไม่สามารถกดปุ่ม OK เพื่อ save action ที่เราใส่เข้าไปได้ หรือกดปุ่ม Finish ที่อยู่ใน form ก็ไม่ได้เช่นกัน ถ้าเคยเจอปัญหานี้ เรามีวิธีแก้ไขมาให้ 2 วิธี โดยทั้ง 2 วิธีเป็นการไปแก้ไข configure ใน web.config ของ SmartForms ที่ site designer (อยู่ใน {install dir}\K2 blackpearl\K2 smartforms Designer)

  • แก้ไขค่า MaxRequestLength จากค่า default เป็น “2097151” ซึ่งเป็นค่ามากที่สุดที่ใส่ได้

designer

  • ถ้าใช้วิธีแรกแล้วยังไม่หาย ให้เพิ่ม tag ตามด้านล่างลงไป ภายใต้ tag requestFiltering

<requestLimits maxAllowedContentLength=”300000000″ />

designer2

เมื่อแก้ไขแล้ว ให้ save web.config และ reset IIS จากนั้นลองใช้งานดู ก็น่าจะ save form ได้ตามปกติครับ  🙂

[K2 SmartForms] – Use SmartObject Property in Custom Control (Part III)

มาต่อจากคราวที่แล้ว ที่เราเลือกเป็น static ไป คราวนี้จะมาลองเลือก SmartObject มาใช้งานกันบ้าง เหมือนกับของ static คือ เราต้องสร้าง property ใน file .cs เพิ่มก่อน โดย property ที่ใช้งานจะมี AssociationSO, AssociationMethod, ValueProperty และ DisplayTemplate

public string AssociationSO

{

get

{

return this.GetOption<string>(“AssociationSO”, string.Empty);

}

set

{

this.SetOption<string>(“AssociationSO”, value, string.Empty);

}

}

public string AssociationMethod

{

get

{

return this.GetOption<string>(“AssociationMethod”, string.Empty);

}

set

{

this.SetOption<string>(“AssociationMethod”, value, string.Empty);

}

}

public string ValueProperty

{

get

{

return this.GetOption<string>(“ValueProperty”, string.Empty);

}

set

{

this.SetOption<string>(“ValueProperty”, value, string.Empty);

}

}

public string DisplayTemplate

{

get

{

return this.GetOption<string>(“DisplayTemplate”, string.Empty);

}

set

{

this.SetOption<string>(“DisplayTemplate”, value, string.Empty);

}

}

สิ่งที่ต้องทำถัดไปคือ สร้าง structure มาเพื่อรับค่าที่เราเก็บไว้ใน DisplayTemplate เพราะตอนที่เราเลือกว่า จะแสดงค่าอะไรออกมาที่ control เราสามารถเลือกได้หลาย field ตามตัวอย่างด้านล่าง

ccb5-01

structure ที่สร้างมาเพื่อรองรับค่า จะใช้ตามด้านล่าง โดยใน DisplayTemplate ที่ K2 เก็บไว้จะเก็บไว้ในรูปของ xml

internal struct DisplayTemplateObject
{

public string SourceType;

public string SourceID;

public string Value;

}

อีกส่วนที่ต้องทำไว้ก่อนคือ การเอา field จาก DisplayTemplate มาต่อกัน เพื่อนำไปใช้ใน control เลยสร้าง method ที่ชื่อ BuildValue ไว้ตามด้านล่าง

private string BuildValue(SmartObject smo, List<DisplayTemplateObject> ParsedTemplate)

{

StringBuilder builder = new StringBuilder();

foreach (DisplayTemplateObject templateObj in ParsedTemplate)

{

if (templateObj.SourceType == “Value”)

{

builder.Append(templateObj.Value);

}

else

{

builder.Append(smo.Properties[templateObj.SourceID].Value);

}

}

return builder.ToString();

}

ทีนี้ก็พร้อมแล้ว เรามาเพิ่ม code ใน CreateChildControls กัน โดยขั้นตอนการทำงานจะทำตาม step ด้านล่าง

  • ตรวจสอบว่า DataSourceType เป็น SmartObject หรือเปล่า?
  • เอาข้อมูล SmartObject, Method และ Value ออกมาจาก property
  • ดึงข้อมูลโดยใช้ class SmartObjectClientServer แบบที่เราเขียนโปรแกรมปกติ
  • ดึงข้อมูล DisplayTemplate มาใส่ใน list โดยแยก attribute มาจาก xml ที่ K2 เก็บไว้ให้
  • นำมาใส่ไว้ใน control ที่ต้องการ

if (this.DataSourceType.Equals(“smartobject”, StringComparison.InvariantCultureIgnoreCase))
{

string smo = this.AssociationSO;
string valueProp = this.ValueProperty;
string smoMethod = this.AssociationMethod;

SmartObjectClientServer smartObjectClient = ConnectionClass.GetSmartObjectClient();
Guid guid = new Guid(smo);
SmartObject smartObject = smartObjectClient.GetSmartObject(guid);
smartObject.MethodToExecute = smoMethod;
SmartObjectList list = new SmartObjectList();

list = smartObjectClient.ExecuteList(smartObject);

List<DisplayTemplateObject> parsedTemplate = new List<DisplayTemplateObject>();

foreach (XElement element in XDocument.Parse(this.DisplayTemplate).Root.Elements())
{

DisplayTemplateObject item = new DisplayTemplateObject

{

SourceType = element.Attribute(“SourceType”).Value

};

if (item.SourceType == “Value”)

{

item.Value = element.Element(“SourceValue”).Value;

}

else

{

item.SourceID = element.Attribute(“SourceID”).Value;

}

parsedTemplate.Add(item);

}

this.ddl = new DropDownList();

List<KeyValuePair<string, string>> showList = new List<KeyValuePair<string, string>>();

foreach(SmartObject item in list.SmartObjectsList)
{

ddl.Items.Add(new ListItem(this.BuildValue(item, parsedTemplate), item.Properties[valueProp].Value));

}

this.Controls.Add(this.ddl);

ในกรณีที่ใส่ code ไปแล้วติด reference บางตัวที่หาไม่เจอ ให้ลอง add dll SourceCode.SmartObjects.Client เพิ่มเข้ามาใน project แล้วก็ add using ตามด้านล่างเข้าไปใน coding ของ control เพิ่ม

using SourceCode.SmartObjects.Client;

using SourceCode.Forms.Controls.Web.SDK.Utilities;

using System.Xml.Linq;

จากนั้นก็ deploy แล้วก็ทดสอบ

ccb5-02

ccb5-03

สำหรับส่วนการ add property ก็จะจบเท่านี้นะครับ เอาไว้พบกันใหม่คราวหน้าครับ 🙂

[Trouble Shooting] – How to solve SmartForms Worklist Control Infinite Spinning

สวัสดีครับ รอบนี้มาคั่นเวลา custom control series นิดหน่อย เนื่องจากเมื่อเช้าได้ช่วยลูกค้าแก้ปัญหา worklist control ของ SmartForms ไม่แสดง worklist ได้แต่หมุนค้างตามรูปด้านล่าง

infiniteworklist01

อย่างแรกที่เราควรไปดูคือ worklist ใน workspace ทำงานได้ไหม? และสามารถใช้งาน service อื่นของ K2 ได้หรือไม่? (service อื่น เช่น start workflow, ใช้งานหน้าจอ SmartForm ที่ไม่มี worklist) ถ้าตรวจสอบแล้วใช้งานได้ ให้ไปดู Web Service URL กับ Web Service URL SSL ใน Environment Library ว่า มีการ set ค่า default ไว้หรือเปล่า?

infiniteworklist02

ถ้าเป็นตามรูปด้านบนที่ไม่ได้ set ไว้ ก็ให้เลือก set อันใดอันหนึ่งให้เป็น default จากนั้น restart service K2 ก็จะสามารถใช้งาน worklist control ของ SmartForms ได้ตามปกติครับ (ถ้ายังไม่ได้ให้ลอง reset IIS กับ clear browser cache ด้วยนะครับ)

ก็ขอจบ tip สั้นๆ ไว้เพียงเท่านี้ ไว้เจอกันใหม่รอบหน้าครับ 😀