K2 Google G Suite Integration [EN Version]

Credit of this blog goes to withsp

Hello today we’ll talk about integration between K2 and Google GSuite. Pre-requisite as below

  • K2 Five version 5.0001.1000.1 or above (version date is 28 Nov 2017)
  • Google account

Firstly, we need to prepare google service that we want to intergrate with. Url for enable service is https://console.developers.google.com/apis. You need to signin with google account. Click Library tab on the left.

google01

In our example we’ll use Google Drive API.

google02

Click Enable button

google03

Then go to tab Credentials and select OAuth consent screen. Select your email and enter Product Name

google05

After Save click at Credentials again and select Create credentials => OAuth client ID

google06

In Create client ID screen select Application Type as Web application and input Name. Input Authorised JavaScript origins as your K2 site url and Authorised redirect URIs as K2 site url append with /identity/token/oauth/2

google07

After created, we’ll get Client ID and Client secret. These will use to register with K2. So we’ll finish setup Google side.

google08

Open your K2 management site and navigate to Authentication => OAuth => Resource Types. Create your new OAuth Resource Type

google10

Next step is create Resource Type Parameters at the bottom view

google11

After finish, navigate to OAuth => Resources. Create your new OAuth Resource and select Resource Type as your created resource from previous step. Input Authorization Endpoint as https://accounts.google.com/o/oauth2/auth and Token Endpoint as https://accounts.google.com/o/oauth2/token

google12

Next step is configure parameter for OAuth Resource

  • client_id and client_secret input information that we got from Google.
  • response_type input Authorization Value as code
  • scope input as https://www.googleapis.com/auth/drive
  • redirect_uri input Authorization Value and Token Value as K2 site url append with /identity/token/oauth/2
  • grant_type input Token Value as authorization_code
  • access_type input Authorization Value and Token Value as online

google13

After finish we’ll have OAuth resource ready to use in service instance configuration. For configure REST service instance we need to have json of service that we want to use. For Google Drive we can search at  https://apis.guru/browse-apis/

google14

Next step we’ll register REST service. Select Authentication Type as OAuth and select our OAuth Resource from previous step

google15

google16

If we found above error, don’t be panic. After you finish OK, system will open browser for you to authentication with google. After you input username password and follow instruction on screen. You will navigate to Authorization Successful screen.

google17

Try adding service instance again. You should be able to create new service instance. Then you can create SmartObject to get data from Google Drive as expected.

google18

Step for create OAuth in K2 reference from https://help.k2.com/kb001702. Google API document can found in google website that you for enable services. If you have question, please feel free to ask. See you next time 🙂

 

Advertisements

K2 Google G Suite Integration [TH Version]

บทความนี้ขอมอบ credit ให้ withsp

สวัสดีครับ วันนี้เราจะมาคุยกันเรื่อง integration ระหว่าง K2 กับอย่างอื่นที่ไม่ใช่ตระกูล Microsoft กันบ้าง นั่นคือ Google GSuite นั่นเอง เรามาดู pre-requitsite กันก่อน

  • K2 Five version 5.0001.1000.1 ขึ้นไป (version นี้ออกวันที่ 28 Nov 2017)
  • Google account

อย่างแรกเลย เราต้องมาเตรียมตัวในฝั่ง Google กันก่อน ให้เข้าไป enable service ที่เราต้องการผ่าน ให้ login เข้าไปด้วย google account ของเราเอง ที่ url https://console.developers.google.com/apis จากนั้นให้กด tab Library ทางด้านซ้าย

google01

ให้เลือก library ที่เราต้องการใช้ ในตัวอย่างนี้เราจะใช้ Google Drive กัน

google02

ให้กดปุ่ม Enable

google03

จากนั้นให้กดที่ tab Credential และเลือก OAuth consent screen ให้เลือก email แล้วก็ใส่ Product Name เป็นอะไรก็ได้

google05

เมื่อกดปุ่ม Save แล้วให้กดกลับไปที่ Credentials แล้วเลือก OAuth client ID

google06

ในหน้า Create client ID ให้เลือก Application Type เป็น Web application และตั้งชื่อ client เป็นอะไรก็ได จากนั้นใส่ Authorised JavaScript origins เป็น url ของเครื่อง K2 กับ Authorised redirect URIs ให้ใส่เป็น url เครื่อง K2 ต่อด้วย /identity/token/oauth/2

google07

เราจะได้ Client ID กับ Client secret มาเพื่อเอาไป register กับ K2 ต่อไป เป็นอันเสร็จสิ้นกระบวนการฝั่ง Google

google08

มาที่ฝั่ง K2 บ้าง ให้เข้าไปที่ site management กดไปที่ Authentication => OAuth => Resource Types ให้สร้าง Resource Type ใหม่ขึ้นมา

google10

เมื่อสร้างเสร็จให้สร้าง Resource Type Parameters ที่ tab ด้านล่าง

google11

จากนั้นให้ไปกดที่ OAuth => Resources ให้สร้าง OAuth Resource ใหม่ขึ้นมา โดยเลือก Resource Type ที่เราสร้างไว้แล้ว และใส่ Authorization Endpoint เป็น https://accounts.google.com/o/oauth2/auth และ Token Endpoint เป็น https://accounts.google.com/o/oauth2/token

google12

กดสร้าง OAuth Resource แล้วก็ไปกำหนดค่า parameter กัน

  • client_id กับ client_secret ให้ใส่ค่าที่ได้มาจาก Google โดย client_secret จะใส่แค่ Authorization Value กับ Token Value
  • response_type ใส่ Authorization Value เป็น code
  • scope ใส่เป็น https://www.googleapis.com/auth/drive
  • redirect_uri ใส่ Authorization Value กับ Token Value เป็น url ของ K2 ต่อด้วย /identity/token/oauth/2
  • grant_type ใส่ Token Value เป็น authorization_code
  • access_type ใส่ Authorization Value กับ Token Value เป็น online

google13

ถ้าทำเสร็จเรียบร้อย เราจะได้ OAuth ที่พร้อมสำหรับเอาไปใช้ register service instance แล้ว ในการจะ register REST service ให้ K2 เราจำเป็นจะต้องมี json ของ service ที่เราจะใช้งาน จะไปเขียน swagger เองก็ได้ แต่ด้วยความที่ Google API เป็นอะไรที่ค่อนข้างจะดัง เราเลยสามารถไปหามาจากที่อื่นได้ ผมไปหามาจาก https://apis.guru/browse-apis/ เราก็จะได้ json มาใช้แล้ว

google14

ขั้นต่อไปให้ไปที่ SmartObject Service Tester หรือใน Management site ก็ได้ แล้วกด Register REST Service เลือก Authentication Type เป็น OAuth และเลือก OAuth Resource เป็นอันที่เราสร้างไว้

google15

google16

ถ้าเจอ error นี้ไม่ต้องตกใจ เมื่อกด OK tester จะเปิด browser ให้เพื่อ authenticate กับ Google ให้ ใส่ username และ password จนถึงหน้า Authorization Successful

google17

ให้กด Add Service Instance อีกที จะสามารถสร้าง Service Instance ได้ จากนั้นก็จะสามารถสร้าง SmartObject เพื่อดึงข้อมูลจาก Google Drive ได้

google18

วิธีการสร้าง oAuth ใน K2 reference มาจาก https://help.k2.com/kb001702 ส่วน api ของ google ดู document ได้จากใน web API ของ Google เลย สำหรับคราวนี้ก็จบเพียงเท่านี้ เจอกันใหม่คราวหน้าครับ 🙂

 

[Authentication] – Using LDAP with K2

สวัสดีครับ ช่วงนี้ได้มีโอกาสทำอะไรใหม่ๆ อีกอย่างเลยเอามาเขียนเป็น blog ซะหน่อย นั่นคือ configure K2 ให้มองเห็น LDAP ที่ไม่ใช่ LDAP ของ AD แต่ถ้าเป็น LDAP ของ AD ก็น่าจะใช้ได้เหมือนกัน โดย step ที่ต้องทำมีตามด้านล่าง

  • Register Security label ของ LDAP
  • Configure Claim ใน SmartForms

 

เรามาเริ่มจาก Register Security label ของ LDAP ให้เปิด database K2 ที่ table HostServer.SecurityProvider

provider

ให้ copy GUID ของ ProviderClassName ที่เป็น SourceCode.Security.Providers.LdapProvider.Trusted.Ldap เอามาใส่ใน script ด้านล่าง ส่วนที่เป็นตัวแปร AuthSecurityProviderID

ส่วนอื่นที่ต้องเปลี่ยนจะมีหลายอันตาม highlight สีน้ำเงิน สามารถไปดูรายละเอียดได้จาก https://help.k2.com/onlinehelp/k2blackpearl/icg/4.7/default.htm#Configure/UM-LDAP-config.htm%3FTocPath%3DConfigure%7CUser%2520Managers%7C_____3 นะครับ

DECLARE @SecurityLabelName NVARCHAR(20) = ‘K2LDAP‘; –Update as needed
DECLARE @XmlConfig XML =
‘<AuthInit><LdapConnection LdapServer=”Server Name” LdapServerPort=”389” LdapSsl=”false” LdapAuthTypeConnect=”Basic” LdapAuthTypeAuthenticateUser=”Basic” LdapResolveAuthenticationUserToDistinguishedName=”true” LdapAutoBind=”false” LdapScope=”Subtree” LdapConnectIntegrated=”false” LdapConnectUserName=”uid=username,ou=People,dc=xxx,dc=xxx” LdapConnectUserPassword=”password” LdapTimeout=”0″ LdapProtocolVersion=”3″ LdapServerCertificatePath=”” /><LdapUserBaseObject>ou=People,dc=xxx,dc=xxx</LdapUserBaseObject><LdapUserSearchFormatString>(uid={0})</LdapUserSearchFormatString><LdapUserGroupSearchFormatString>(memberOf={0})</LdapUserGroupSearchFormatString><LdapUserAttributes><K2LdapMapping K2Name=”ID” LdapName=”uid” ObjectType=”System.String” /><K2LdapMapping K2Name=”Name” LdapName=”uid” ObjectType=”System.String” /><K2LdapMapping K2Name=”Email” LdapName=”mail” ObjectType=”System.String” /><K2LdapMapping K2Name=”CommonName” LdapName=”cn” ObjectType=”System.String” /><K2LdapMapping K2Name=”UserPrincipalName” LdapName=”uid” ObjectType=”System.String” /><K2LdapMapping K2Name=”DisplayName” LdapName=”cn” ObjectType=”System.String” /><K2LdapMapping K2Name=”Mobile” LdapName=”mobile” ObjectType=”System.String” /></LdapUserAttributes><LdapGroupBaseObject>ou=Group,dc=xxx,dc=xxx</LdapGroupBaseObject><LdapGroupSearchFormatString>(uid={0})</LdapGroupSearchFormatString><LdapGroupMemberSearchFormatString>(cn={0})</LdapGroupMemberSearchFormatString><LdapGroupAttributes><K2LdapMapping K2Name=”ID” LdapName=”cn” ObjectType=”System.String” /><K2LdapMapping K2Name=”Name” LdapName=”cn” ObjectType=”System.String” /><K2LdapMapping K2Name=”Email” LdapName=”mail” ObjectType=”System.String” /><K2LdapMapping K2Name=”Member” LdapName=”member” FullOnly=”true” SearchQuery=”(&amp;(objectCategory=Person)(objectCategory=User))” SearchResultProperty=”cn” ObjectType=”System.Collections.ArrayList” /></LdapGroupAttributes></AuthInit>’
DECLARE @SecurityLabelID UNIQUEIDENTIFIER = NEWID(); –Assigning new GUID
DECLARE @AuthSecurityProviderID UNIQUEIDENTIFIER = ‘EE554827-1C61-46EF-9146-293CE74E55C9‘;
DECLARE @AuthInit XML = @XmlConfig;
DECLARE @RoleSecurityProviderID UNIQUEIDENTIFIER = @AuthSecurityProviderID;
DECLARE @RoleInit XML = @XmlConfig;
DECLARE @DefaultLabel BIT = NULL; –1 = true, NULL and 0 = false

DELETE FROM [SecurityLabels] WHERE SecurityLabelName = @SecurityLabelName;
INSERT INTO [SecurityLabels] VALUES (@SecurityLabelID, @SecurityLabelName, @AuthSecurityProviderID, @AuthInit, @RoleSecurityProviderID, @RoleInit, @DefaultLabel)

จะมีบางอันที่อาจจะหาลำบากคือ ldapname กับ userbaseobject แนะนำให้ใช้พวก ldap browser เช่น http://www.ldapadministrator.com หรือ http://www.ldapadmin.org เพื่อหาข้อมูลที่ถูกต้องได้

ldap browser

เมื่อได้ script เรียบร้อย เราก็เอาไปรันใน database K2

LDAP Register

เสร็จแล้วให้ restart service K2 และเราก็พร้อมที่จะทำ step ถัดไป คือการ configure claim ให้เข้าไปที่ management site ของ K2 ไปที่ Authentication => Claims => Claims แล้วกด New

02

ใส่ข้อมูลตามด้านล่าง

03

กดปุ่ม OK แล้วไปทดสอบด้วยการ login ผ่าน form ได้เลย

Login

ถ้าใครไปลองแล้วติดอะไรก็สอบถามได้นะครับ ในส่วนของ blog นี้ ใช้ได้กับทั้ง K2 Five และ K2 blackpearl นะครับ ลองแล้วใช้งานได้ทั้ง 2 version ครับ ไว้เจอกันใหม่คราวหน้าครับ 🙂

[K2 Five] – Workflow REST & SMO OData

สวัสดีครับ วันนี้เราจะมาพูดถึง API ที่เราน่าจะได้ใช้กันบ่อยๆ คือ REST service ของ Workflow และ SmartObject

Workflow REST API

โดยสิ่งที่จะต้องทำเป็นอย่างแรกเลยคือ ไป enable service ใน Management site ก่อน

Workflow REST API Setting

หลังจากเปิดแล้วจะได้ตามด้านล่าง

Workflow REST API Setting Enable

เราสามารถทดสอบ API ได้จาก Swagger URL ด้วย

Workflow Swagger URL

Workflow Swagger Result

โดยตัวอย่างการใช้งานโดยเรียกจาก application อื่นๆ สามารถดูได้จาก https://help.k2.com/onlinehelp/k2five/DevRef/5.0/default.htm#Runtime/WF-REST/REST-Samples.htm

SmartObject OData API

เหมือนกับ Workflow REST API ต้องไปเปิดใน management site ก่อน (ถ้าเป็น version ก่อนๆ เราจะต้องไปเปิดใน config ตามวิธีใน  https://help.k2.com/onlinehelp/k2blackpearl/DevRef/4.7/default.htm#Configuration2.html)

SMO Service Setting

หลังจากเปิดแล้วจะเป็นตามด้านล่าง เราสามารถเลือก SmartObject ที่ต้องการ exposed เป็น REST service ได้ด้วย

SMO Server Setting Enable

ทีนี้พอเปิดแล้วเราก็มาลองกันซักหน่อย วิธีง่ายที่สุดคือ ใช้ Excel โดยเลือก Import Data From OData Data Feed

Excel OData

ใส่ link และ credential

Excel Data Connection Wizard

ใน wizard จะมี SmartObject ให้เลือก

List SMO

จากนั้นจะให้เลือก Import Data เป็นแบบไหน

Excel Import Data

จากนั้นก็จะได้ข้อมูลอย่างที่เราต้องการ 🙂

Excel

สำหรับรายละเอียด สามารถดูเพิ่มเติมได้จาก https://help.k2.com/onlinehelp/k2five/DevRef/5.0/default.htm#Runtime/SmO-REST/SmORESTServices.htm%3FTocPath%3DRuntime%2520APIs%2520and%2520Services%7CSmartObjects%7CSmartObject%2520REST%2520Services%7C_____0 ครับ

[K2 for SharePoint] – Configuration Tip สำหรับ SharePoint 2016

สวัสดีครับ รอบนี้ได้ configure K2 4.7 กับ SharePoint 2016 มาเลยมี tip เพิ่มเติมจาก blog รอบที่แล้ว (ดูได้ที่นี่) มาให้อ่านกัน

ก่อนลง SharePoint 2016 จะเหมือนกับ 2013 คือ ต้องลง prerequisite installer ก่อน แต่ในรอบนี้ ถึงแม้ server เราจะต่อ internet ได้แต่ก็ไม่สามารถ download อะไรได้เลย สุดท้ายก็ต้องมา download เอง แต่เดี๋ยวก่อน!! ถ้าเรา download มาเองแล้วมาลงเอง อาจจะ error ใน step configure SharePoint ได้ ใน step นี้ แนะนำ http://nikcharlebois.com/installing-the-sharepoint-2016-prerequisites-offline-using-powershell/ ให้ download file จากในนี้ได้เลย และให้ใส่ command ตาม เป็นอันจบ

Step หลังจากนี้ ก็ทำเหมือนกับ SharePoint 2013 เลย หลังจากลงเสร็จก็ enable service ตามด้านล่าง (แนะนำให้ใช้ command line ทั้งหมด เพราะว่า ถ้าทำผ่าน UI จะ set บางส่วนไม่ได้)

  • Subscription Service

    $account = Get-SPManagedAccount <Account Name>
    $appPoolSubSvc = New-SPServiceApplicationPool -Name SettingsServiceAppPool -Account $account
    $appSubSvc = New-SPSubscriptionSettingsServiceApplication -ApplicationPool $appPoolSubSvc -Name SettingsServiceApp -DatabaseName <Database Name>
    $proxySubSvc = New-SPSubscriptionSettingsServiceApplicationProxy -ServiceApplication $appSubSvc

  • App Management Service

    $account = Get-SPManagedAccount <Account Name>
    $appPoolAppSvc = New-SPServiceApplicationPool -Name AppServiceAppPool -Account $account
    $appAppSvc = New-SPAppManagementServiceApplication -ApplicationPool $appPoolAppSvc -Name AppServiceApp -DatabaseName <Database Name>
    $proxyAppSvc = New-SPAppManagementServiceApplicationProxy -ServiceApplication $appAppSvc

  • User Profile Service

    $appPool = New-SPServiceApplicationPool -Name HostedAppPool -Account (Get-SPManagedAccount “<Account Name>“)
    $app_UPA = New-SPProfileServiceApplication -Name UPA -PartitionMode -ApplicationPool $appPool

    ตรงนี้จะมีความต่างจาก SharePoint 2013 นิดหน่อย ตรงที่ไม่มี User Profile Synchronization Service ให้ start แต่ในมุมของเราให้สร้าง User Profile Service ให้เรียบร้อย พอสร้างแล้วจะมีปุ่มให้กด Manage

UPS01

Configure Synchronization Connections ให้เรียบร้อย ก็จะใช้งานได้ปกติ

UPS02

UPS03

  • Enable NetBIOS สำหรับ User Profile Service Name ให้ไปดูที่หน้า App Management Service แล้วใส่ชื่อตาม

    $UserProfileServiceApp = Get-SPServiceApplication -name <User Profile Service Name>
    $UserProfileServiceApp.NetBIOSDomainNamesEnabled = 1
    $UserProfileServiceApp.Update()

  • Shell Admin grant SPShellAdmin ให้ user ที่จะเป็นคนรัน app deployment

    Add-SPShellAdmin -UserName <Account Name>
    Get-SPDatabase | ?{$_.Name -eq “<WSS Content DB>“} | Add-SPShellAdmin -Username <Account Name>
    Get-SPDatabase | ?{$_.Name -eq “<SharePoint Admin DB>“} | Add-SPShellAdmin -Username <Account Name>
    Get-SPDatabase | ?{$_.Name -eq “<SharePoint Config DB>“} | Add-SPShellAdmin -Username <Account Name>
    Get-SPDatabase | ?{$_.Name -eq “<App Management Service DB>“} | Add-SPShellAdmin -Username <Account Name>
    Get-SPDatabase | ?{$_.Name -eq “<User Profile Service DB>“} | Add-SPShellAdmin -Username <Account Name>
    Get-SPDatabase | ?{$_.Name -eq “<User Profile DB>“} | Add-SPShellAdmin -Username <Account Name>

ถ้าทำเรียบร้อยก็ให้รัน K2 for SharePoint App Deployment ได้เลย 🙂

Consume REST Services with K2

สวัสดีครับ เนื่องจากใน K2 4.7 มี broker ใหม่เพิ่มเข้ามา และเป็น broker ที่เราน่าจะได้ใช้กันเยอะในอนาคต broker ตัวนี้ก็คือ REST service broker นั่นเอง

การเชื่อมต่อ REST service ใน K2 จะแตกต่างจากการเชื่อมต่อ web service อื่นๆ อยู่ตรงที่ เรารู้แค่ url ของ web service นั้นไม่พอ สิ่งที่ต้องมีถัดไปคือ descriptor file ใน format ของ JSON ถ้าเป็น REST service ที่เราเขียนเองก็อาจจะไม่ยาก เพราะเราสามารถ generate JSON ออกมาจาก swagger ที่เราเขียนได้ แต่ถ้าไม่ได้เขียนเองมี option ตามด้านล่าง

โดยในส่วนที่อยู่ใน blog นี้จะเป็นการเขียนเอง

ถ้าจะเขียน descriptor เอง เราควรรู้อะไรบ้าง?

  • Format ที่ REST Service response ออกมา
  • Swagger syntax ที่จะใช้เขียน เพื่อทำ mapping กับ service ที่เราจะใช้

ผมเลือก service จาก Accuweather (https://developer.accuweather.com) มาลองดู สามารถสมัครมาลองใช้ได้ฟรี แต่ service ก็จะ limit หน่อย (ถ้าใครอยากลอง ก็ไปสมัครแล้ว register app ก็จะได้ API Key ที่ต้องใช้ในมา) ใช้ได้ไม่กี่อัน แต่หลักๆ ของ service ที่มีให้คือ การพยากรณ์ต่างๆ

Weather API

ที่เราจะใช้กันคือ Location API เพื่อหาพื้นที่ที่ต้องการ กับ Forecast API เพื่อดูพยากรณ์ (จริงๆ อยากใช้ Weather Alerts มากกว่า แต่แบบฟรีใช้ไม่ได้ T-T)  อย่างที่บอก เริ่มแรกคือ ต้องไปลองเรียก REST Service เพื่อให้ return response มาซะก่อน

API Response

พอได้ response เราก็เอามาเขียน swagger เพื่อที่จะ generate เป็น descriptor กัน รายละเอียดเกี่ยวกับ swagger ลองอ่านดูตาม link ด้านล่างนะครับ

Tool ที่ผมใช้ในการเขียน swagger ก็มาจาก swagger.io นี่แหละ ใช้เป็นแบบ online เลยง่ายดี สามารถเข้าไปได้ที่ http://editor.swagger.io  ถ้าเขียนเสร็จแล้วก็น่าจะได้ format แบบด้านล่างนี่ล่ะ

Swagger UI

สิ่งที่ควรระวังตอนเขียน swagger คือ ในบางกรณีที่เรามีการเรียกใช้ reference object ซ้อนๆ กัน การประกาศบางแบบอาจจะเรียกใช้ไม่ได้ใน K2 นะครับ แบบที่ใช้ได้จะมีตัวอย่าง file swagger ที่เขียนให้ download ตอนท้ายบทความครับ

เมื่อเขียนเรียบร้อย เราสามารถ generate JSON file ได้โดยเลือกเมนู File -> Download JSON

Download JSON

พอได้ file มา เราก็เอามา register กับ K2 โดยผ่าน SmartObject Service Tester

02-Register REST

03-Register 2

หลังจาก register แล้ว เราก็จะเห็น object ที่สามารถเรียกได้ตามด้านล่าง

04-After Regist

จะเห็นว่า มี method พวก Serialize กับ Deserialize มาด้วย method พวกนี้จะเป็น method สำหรับดึงค่าจาก type ที่ return มาเป็น structure เหมือนกับที่เราใช้ K2 ต่อกับ SAP หรือ web service อื่นๆ จากนั้นลองสร้างเป็น smartobject แล้วทดสอบดู

05-Test City Search

อย่างแรกเลยคือ call City Search เพื่อหาเมือง เพิ่งรู้นะเนี่ยว่า กรุงเทพฯ มีที่อินโดนีเซียด้วย พอได้แล้ว ผมก็เอา Key ไปใช้เพื่อหา forecast ของ 5 วันข้างหน้า

06-5 day forecast

ใน method นี้จะ return Headline หรือคือ พาดหัวข่าวสำคัญ เช่น ฝนจะตกหนักวันไหน กับรายละเอียด forecast มาเป็น object ส่วนที่เราต้องทำถัดไปคือ เอา xml ยาวๆ ที่ได้ ไป call method Deserialize เพื่อให้แสดงผลออกมาเป็น property ออกมา

ส่วนของ Headline ผมได้ xml ตามด้านล่างออกมา

{“$type”:”Accuweather.k2RESTidentifier_Headline, Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”EffectiveDate”:”2017-08-13T01:00:00+07:00″,”Text”:”A thunderstorm late Saturday night”,”Category”:”thunderstorm”,”Link”:”http://www.accuweather.com/en/th/bangkok/318849/daily-weather-forecast/318849?lang=en-us&#8221;}

ผลหลังจากการ call โอ๊ะ!!! ฝนตกหนักคืนวันเสาร์ตอนดึกๆ

07-Headline Call

ส่วนของพยากรณ์จะได้เป็น array ออกมา

{“$type”:”Accuweather.k2RESTidentifier_DailyForecast[], Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”$values”:[{“$type”:”Accuweather.k2RESTidentifier_DailyForecast, Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”Date”:”2017-08-10T07:00:00+07:00″,”Link”:”http://www.accuweather.com/en/th/bangkok/318849/daily-weather-forecast/318849?day=1&lang=en-us&#8221;},{“$type”:”Accuweather.k2RESTidentifier_DailyForecast, Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”Date”:”2017-08-11T07:00:00+07:00″,”Link”:”http://www.accuweather.com/en/th/bangkok/318849/daily-weather-forecast/318849?day=2&lang=en-us&#8221;},{“$type”:”Accuweather.k2RESTidentifier_DailyForecast, Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”Date”:”2017-08-12T07:00:00+07:00″,”Link”:”http://www.accuweather.com/en/th/bangkok/318849/daily-weather-forecast/318849?day=3&lang=en-us&#8221;},{“$type”:”Accuweather.k2RESTidentifier_DailyForecast, Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”Date”:”2017-08-13T07:00:00+07:00″,”Link”:”http://www.accuweather.com/en/th/bangkok/318849/daily-weather-forecast/318849?day=4&lang=en-us&#8221;},{“$type”:”Accuweather.k2RESTidentifier_DailyForecast, Accuweather, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,”Date”:”2017-08-14T07:00:00+07:00″,”Link”:”http://www.accuweather.com/en/th/bangkok/318849/daily-weather-forecast/318849?day=5&lang=en-us&#8221;}]}

ผลหลังจากการ call ก็เป็นตามด้านล่าง

08-DailyForecast Call

จริงๆ ค่าที่ REST return มามีมากกว่าที่ผมเอามาแสดง แต่ผมเขียน swagger เพื่อเอาค่ามาเฉพาะที่ต้องการเท่านั้น (ขี้เกียจนั่นเอง = =’) ถ้าใครอยากดูตัวอย่างการเขียน swagger กับ file JSON ที่ generate ออกมาได้สามารถ download ได้ตาม link ด้านล่างนะครับ

สำหรับคราวนี้ก็ขอลาแต่เพียงเท่านี้ พบกันใหม่คราวหน้าครับ 🙂

 

 

 

 

[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 สั้นๆ ไว้เพียงเท่านี้ ไว้เจอกันใหม่รอบหน้าครับ 😀