가끔.. 데이터 베이스 파일을 백업 받고..

옮겨서 복원하는 경우가 있습니다.

헌데 로그 파일의 사이즈가 너무 큰 경우..

 

복원하고 나니.. 하드가 모자라서.. 사이즈 조정이 필요한 경우..

아래와 같이 하시면 됩니다.

 

SP_HELPDB PORTALSTATISTICS

USE DataBaseName;
ALTER DATABASE DataBaseName
SET RECOVERY SIMPLE;
GO

DBCC SHRINKFILE (DataBaseName_log, 1);
GO

ALTER DATABASE DataBaseName
SET RECOVERY FULL;
GO

 

SP_HELPDB를 이용해서 축소하고자 하는 Database의 Log 파일 명을 알아냅니다.

 

그리고 위에 보이는 Database_log 의 이름을 해당 디비 이름으로 변경하시고.. 위의 쿼리를 실행하면 아래와 같이 쭈욱 쭐어드는 것을 볼 수 있습니다.

 

쿼리 실행결과는 아래와 같습니다.

 

이상입니다.


언어팩을 설치한 후 마법사를 돌리면 아래와 같이 에러가 나타납니다.

이유는 쉐어포인트 2010에서는 Office 2013을 지원하지 않기 때문입니다.

예.. 그렇습니다.

저는 쉐어포인트 핫픽스까지 설치 하고 난 후 언어팩을 잊고 오피스를 설치 한 후에 언어팩을 설치 하니..

아래와 같은 에러가 발생 되었습니다.

Could not load file or assembly 'Microsoft.Office.InfoPath, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. 지정된 파일을 찾을 수 없습니다.

방법은….

오피스 2013에서 Infopath만 삭제!

그러면 아래와 같이 성곡적으로 마법사를 구성할 수 있습니다.


고맙습니다.


개발이 끝나는 무렵… 이제 성능 테스트와… 벌래(bug)를 찾아 삼만리 하게 됩니다.

쉐어포인트에는 참 좋은 성능 확인과 벌래 잡이용 대시보드라는게 있습니다.

 

일단 실행은 아래와 같이 입력하시면 됩니다.

Sharepoint 2010 Management Shell을 실행하고..

 

아래와 같이 입력하시면 됩니다.

시작
stsadm -o setproperty -pn developer-dashboard -pv on

종료
stsadm -o setproperty -pn developer-dashboard -pv off

 

위의 내용은 아래 링크에서 좀 더 자세히 볼 수 있습니다.

http://msdn.microsoft.com/en-us/library/ff512745.aspx

 

그리고 실행하게 되면 아래와 같은 화면을 볼 수 있습니다.

 

여기에서 좌측의 노란 색 영역은 현재 페이지에 실행되는 액션 대비 시간이라고 생각하시면 되고..

우측의 상단 빨간색 영역은 오류내용을 표시합니다.

선택 시 좀 더 자세한 내용을 확인 할 수 있고요..

빨간 색의 내용 중 90hv에 관한 내용은 이전에 적어 놓은 포스트에서 확인 하시기 바랍니다.

2013/03/07 - [SharePoint 2010/Development] - Sharepoint 2010 - Detected use of SPRequest for previously closed SPWeb object



그리고 마지막 우측하단 파란색 영역은 실행된 모든 프로시저에 관한 내용을 확인 할 수 있습니다.

여기 프로시저에서 중요한 내용이 있는데..

DECLARE @DocParentIdForRF 라고 되어 있는 프로시저의 경우에는 한번씩 확인을 해 줘야 합니다.

 

해당 프로시저를 선택하면 위와 같이 자세한 내용을 볼 수 있습니다.

제가 하이라이트 표시 해 놓은 부분에 만약 SELECT TOP (@NUMROWS) 라고 되어 있다면 @NUMROWS의 VALUE도 확인하셔야 합니다.

아래와 같이 2,147,483,648 으로 설정될 수 있습니다.

 

성능상의 문제가 될 수 있는 요인이 있기 때문에 반드시 확인하셔야 합니다.

해당 코드는 대략 아래와 같이 구분 할 수 있습니다.

  • SP Item의 인덱스 접근 말고 GetItemById 등과 같은 코드로 접근 할 것
    • item = targetList.Items[int]; X
    • item = targetList.GetItemById(int); O
  • SPQuery 사용 시 반드시 RowLimit를 지정 할 것!
    • Query.RowLimit = 10;
  • 게시판의 카운트를 구할 때 List.ItemCount 와 같이 접근 할 것
    • int total = SPContext.Current.List.Items.Count; X
    • int total = SPContext.Current.List.ItemCount; O

 

위와 같이 해 주시면 저런 21억 Row 쿼리가 실행 되지 않습니다.

 

그리고 위의 화면에 짤린 부분이 있습니다.

 

이 부분인데 Service Calls 부분에서 WebPart Events Offsets 부분만 확인하시면 됩니다.

여기에는 각 웹파트 별로  OnLoad 시점의 시간이 나타나게 되는데요…

급격히 증가하는 웹파트를 찾아서.. 튜닝해 주는 방법을 이용하시면 됩니다.

 

이렇게만 확인해 주셔도.. 페이지의 로딩시간 단축을 확인 할 수 있습니다.

이상입니다.

 

고맙습니다.


개발자 대시보드를 켜 놓고 확인을 하다가 아래와 같은 메시지를 보게 되었습니다.

 

General Unexpected 90hv Detected use of SPRequest for previously closed SPWeb object.  Please close SPWeb objects when you are done with all objects obtained from them, but not before.

 

 

 

위의 메시지는 그 동안 개발하면서 많이 보아 오던 것입니다.

이 녀석이 왜 나타난건지 찾아보게 되었습니다.

저는 SPWeb 객체를 재대로 닫지 않았을 거라고 생각했는데 그게 아니더군요…

 

제가 주로 SPWeb 객체를 사용하는 방법은 일단 아래와 같습니다.

using (SPSite oSite = new SPSite(strListUrl, oUserToken))
using (SPWeb oWeb = oSite.RootWeb)
{
}

 

위의 에러는 아래와 같은 상황에서 발생됩니다.

SPFile oFile = null;
using (SPSite oSite = new SPSite(strListUrl, oUserToken))
using (SPWeb oWeb = oSite.RootWeb)
{
	oFile = oWeb.GetFile("~fileUrl");
}

 

SP 객체를 Web Scope 안에서 해제되도록 코딩 되어야 하는 것입니다.

위의 코드를 아래와 같이 변경하여 처리 해야 하는 거이지요..

string strTitle = String.Empty;
using (SPSite oSite = new SPSite(strListUrl, oUserToken))
using (SPWeb oWeb = oSite.RootWeb)
{
	SPFile oFile = oWeb.GetFile("~fileUrl");
	strTitle = oFile.Title;
}
if(String.IsNullOrEmpty(strTitle))
{
	// 처리
}

 

이렇게 하면 해당 에러가 사라지는 것을 확인 할 수 있습니다.

 

고맙습니다.


MySite User Profile이 없는 경우 생성하는 코드를 입력하고 CreateUserProfile, CreatePersonalSite 을 실행하면 아래와 같은 에러가 발생합니다.

Access Denied: To create a user profile, you must be an administrator, or create your own profile and have personal features rights.

 

제가 작성한 코드는 아래와 같습니다.

SPSecurity.RunWithElevatedPrivileges(delegate()
{
	using (SPSite oSite = new SPSite(strSiteUrl))
	{
		SPServiceContext context = SPServiceContext.GetContext(oSite);
		UserProfileManager profileManager = new UserProfileManager(context);
		UserProfile userProfile;
		if (!profileManager.UserExists(strAccountName))
		{
			SPContext.Current.Site.AllowUnsafeUpdates = true;
			SPContext.Current.Web.AllowUnsafeUpdates = true;
			userProfile = profileManager.CreateUserProfile(strAccountName);
			SPContext.Current.Web.AllowUnsafeUpdates = false;
			SPContext.Current.Site.AllowUnsafeUpdates = false;
		}
	}
});

위의 문제는 UserProfile에 접근 권한이 없어서 발생되는 것입니다.

아래와 같이 진행하시면 됩니다.

  1. 중앙관리로 이동
  2. 응용프로그램 관리 –> 서비스 응용 프로그램 관리
  3. UserProfile Services 선택 후 리본 메뉴의 관리자 선택
  4. 시스템 관리자 계정 입력 후 모든 권한 체크

를 하시면 됩니다.

이미지로 보시면 아래와 같습니다.

 

그리고 난 후 UserProfile을 생성하시면 정상적으로 생성 됩니다.

추가로 제가 AllowUnsafeUpdate가 없는 경우 아래와 같은 에러메시지가 나타납니다.

The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.

 

위의 메시지 때문에 아래의 코드를 입력한 것이니 참고 하시기 바랍니다.

			SPContext.Current.Site.AllowUnsafeUpdates = true;
			SPContext.Current.Web.AllowUnsafeUpdates = true;

			SPContext.Current.Web.AllowUnsafeUpdates = false;
			SPContext.Current.Site.AllowUnsafeUpdates = false;

 

이상입니다.

 

고맙습니다.


자바스크립트로 마지막 글자에 포커스 하는 방법입니다.

모든 브라우져에서 테스트해 보진 않았지만.

IE 8,9, Chrome 에서 테스트 해 봤습니다.

 

	function focusCampo(id) {
		var inputField = document.getElementById(id);
		if (inputField != null && inputField.value.length != 0) {
			if (inputField.createTextRange) {
				var FieldRange = inputField.createTextRange();
				FieldRange.moveStart('character', inputField.value.length);
				FieldRange.collapse();
				FieldRange.select();
			}
			else if (inputField.selectionStart || inputField.selectionStart == '0') {
				var elemLen = inputField.value.length;
				inputField.selectionStart = elemLen;
				inputField.selectionEnd = elemLen;
				inputField.focus();
			}
		}
		else {
			inputField.focus();
		}
	}

 

출처는 아래와 같습니다.

http://stackoverflow.com/questions/4609405/set-focus-after-last-character-in-text-box

 

고맙습니다.


한 동안 쉐어포인트 개발만 하다가 오늘 ASP.NET을 좀 사용하게 되어서 개발을 마치고 확인하던 중..

IE에서는 잘 보이는데 크롬에서 메뉴가 이상하게 나타나는 현상을 보게 되었습니다.

Rander 이벤트 부분을 전혀 타지를 않네요…

 

일단 저는 System.Web.UI.WebControls.Menu를 상속받아서 커스텀 컨트롤로 만든 상태이구요..

아래와 같이 IE에서는 정상적으로 나오는 것을 확인 할 수 있습니다.

 

헌데 크롬에서는 아래와 같이 나타납니다.

 

클릭해 보면 크롬의 경우 버튼으로 구현되어 자기 스스로 랜더링 부분을 확!!! 바꿔 버린 상태입니다.

검색하니 바로 나오긴 하네요..

 

방법은 코드를 넣는 방법과 그리고 ASP_Browsers 폴더에 browser 파일을 이용하는 방법이 있습니다.

일단 코드는 아래와 같이 작성하시면 됩니다.

protected void Page_PreInit(object sender, EventArgs e)
{
	if (Request.ServerVariables["http_user_agent"].IndexOf("Safari", StringComparison.CurrentCultureIgnoreCase) != -1)
	{
		Page.ClientTarget = "uplevel";
	}
}

// 혹은 아래와 같은 방법!

protected void Page_PreInit(object sender, EventArgs e)
{
	if (Request.UserAgent.Contains("AppleWebKit"))
		Request.Browser.Adapters.Clear();
}

 

그리고 Browser파일을 이용하는 방법은 프로젝트 파일에서 마우스 오른쪽 –> 추가 –> ASP.NET 폴더 추가 –> App_Browsers 추가 그리고 생성된 폴더에서 마우스 오른쪽 –> 추가 –> 새 파일 추가 –> browser 파일 선택 후 파일명은 chrome.browser 로 합니다.

 

그리고 아래 부분 코드 추가

<browsers>
	....
	<browser refID="Safari1Plus">
		<controlAdapters>
			<adapter controlType="System.Web.UI.WebControls.Menu" adapterType="" />
		</controlAdapters>
	</browser>
</browsers>

그리고 아직 운영에서 직접 돌려본 경험이 없어서. 어떻게 되는지 정확히는 말씀 못 드리겠습니다. ㅡ.ㅡ;;;;

일단 잘 나오긴 합니다. *_*

 

고맙습니다.


 

마이 사이트 쪽을 개발하다가 기존의 Colleagues 웹파트를 추가하고 사용자를 추가하고 난 후 사용자가 하나의 Row로 보이는 것이 아니라 웹파트의 크기 만큼 셀로 보이는 문제가 발생하였습니다.

 

일단 웹파트를 입력한 후 페이지에서 보게 되면 아래와 같이 보이게 됩니다.

 

웹파트 속성을 보게 되면 속성에는 몇 Row를 보이게 할 것인가 라는 속성과 이름이 보일지 말지 결정하는 속성 두가지 밖에 없습니다.

 

이게 셀단위로 증가 되는 경우는 폭이 80 이상이 경우 80으로 나눠서 샐을 만들고 데이터를 입력하는 형태로 개발되어 있습니다.

웹파트에서요…

 

개발되어 있는 곳도 portal.js에서 구형되어 있어 스크립트로만 구현하면 됩니다.

저는 아래와 같이 만들었으며 사이즈 계산하는 곳만 잘 해 놓으시면 될 것 같습니다.

 

소스는 아래와 같습니다.

저는 person.aspx에 넣어 놓았으며, portal.js 보다 아래 쪽에서만 구현되면 됩니다.

/// portal.js override
function MySite_RenderPeople(h, a, c, d, j) {
	ULSX84: ;
	if (j) {
		var k = function () {
			ULSX84: ;
			MySite_RenderPeople(h, a, c, d, false)
		};
		AttachEvent("domLoad", function () {
			ULSX84: ;
			setTimeout(k, 50)
		});

		return
	}

	if (c < 1)
		c = 1;

	// var i = document.getElementById(h), f = i.clientWidth, e = d ? 80 : 55, b = Math.floor(f / e);
	var i = document.getElementById(h), f = i.clientWidth, e = d ? 230 : 55, b = Math.floor(f / e);
	if (b > a.length) {
		b = a.length;
		e = Math.floor(f / b)
	}
	var g = Math.min(a.length, c * b);
	_MySite_RenderPeople(i, a, 0, g, b, e, d, true);

	return g == a.length
}

MySite_RenderPeople 메소드에서 위의 소스에 주석되어 있는 부분에 80을 원하는 넓이 값으로만 변경하시면 됩니다.
이상입니다.
 
고맙습니다.


my site 관련 된 작업을 진행하다가 사이트를 삭제하고 다시 생성하려고 하는데.. 생성이 되지 않았습니다.

 

에러 내용은 아래와 같습니다.

Exception attempting to ApplyWebTemplate to SPSite http://my.dev.doosan.com: Microsoft.SharePoint.SPException: A list, survey, discussion board, or document library with the specified title already exists in this Web site.  Please choose another title. ---> System.Runtime.InteropServices.COMException (0x81020012): A list, survey, discussion board, or document library with the specified title already exists in this Web site.  Please choose another title.     at Microsoft.SharePoint.Library.SPRequestInternalClass.ApplyWebTemplate(String bstrUrl, String bstrWebTemplateContent, Int32 fWebTemplateContentFromSubweb, Int32 fDeleteGlobalListsWithWebTemplateContent, String& bstrWebTemplate, Int32& plWebTemplateId)     at Microsoft.SharePoint.Library.SPRequest.ApplyWebTemplate(String bstrUrl, String bstrWebTemplateContent, Int32 fWebTemplateContentFromSubweb, Int32 fDeleteGlobalListsWithWebTemplateContent, String& bstrWebTemplate, Int32& plWebTemplateId)     --- End of inner exception stack trace ---     at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)     at Microsoft.SharePoint.Library.SPRequest.ApplyWebTemplate(String bstrUrl, String bstrWebTemplateContent, Int32 fWebTemplateContentFromSubweb, Int32 fDeleteGlobalListsWithWebTemplateContent, String& bstrWebTemplate, Int32& plWebTemplateId)     at Microsoft.SharePoint.SPWeb.ApplyWebTemplate(String strWebTemplate)     at Microsoft.SharePoint.ApplicationPages.TemplatePickerUtil.ApplyWebTemplateAndRedirect(SPSiteAdministration siteAdministration, String strWebTemplate, String strRedirect, Boolean bCreateDefaultGroups, Page page, Boolean bDeleteOnError) Attempting to delete the site collection.

 

아래와 같은 내용도 있습니다.

System.Runtime.InteropServices.COMException: A list, survey, discussion board, or document library with the specified title already exists in this Web site.  Please choose another title.    at Microsoft.SharePoint.Library.SPRequestInternalClass.ApplyWebTemplate(String bstrUrl, String bstrWebTemplateContent, Int32 fWebTemplateContentFromSubweb, Int32 fDeleteGlobalListsWithWebTemplateContent, String& bstrWebTemplate, Int32& plWebTemplateId)     at Microsoft.SharePoint.Library.SPRequest.ApplyWebTemplate(String bstrUrl, String bstrWebTemplateContent, Int32 fWebTemplateContentFromSubweb, Int32 fDeleteGlobalListsWithWebTemplateContent, String& bstrWebTemplate, Int32& plWebTemplateId)

 

좀 찾아보니..

onet.xml 등의 사이트 템플릿 xml이 삭제되거나 했을 경우에 발생되는 에러입니다.

 

저는 my site를 만들면서 해당 onet.xml과 특정 파일들을 직접 수정하는 작업을 진행하였는데.

Web Application을 삭제하면서 같이 삭제 된 것 같습니다.

 

즉. 다시 onet.xml을 살려 놓으면 됩니다.

 

그리고 IIS Reset..

그러면 정상적으로 생성되는 것을 확인 할 수 있습니다.

 

이상입니다.

 

고맙습니다.


Sharepoint my site의 URL은 항상 기본 domain으로 구성되어 있습니다.

도메인을 변경하기 위해서는 일단 먼저 새로운 어플리케이션으로 만드셔야 합니다.

그리고 나서 대체 액세스 맵핑을 설정하여 진행하시면 됩니다~

 

이번에는 Web App 생성 및 구성 그리고 중앙관리에서의 설정 방법에 대해 다뤄 보고자 합니다.

 

저의 현재 PC에 설정되어 있는 Web App는 아래와 같습니다.

 

mySite 접속 시 아래와 같이 ae-dev라는 컴퓨터 명으로 접속되도록 설정되도록 되어 있습니다.

 

먼저 중앙관리에서 새로운 Web App를 만들어 보도록 하겠습니다.

  1. 중앙관리 –> 응용 프로그램 관리로 접속
  2. 웹 응용 프로그램 –> 웹 응용 프로그램 관리로 접속
  3. 상단의 리본 메뉴에서 새로 만들기 선택
  4. 포트 및 호스트 헤더 설정 그리고 확인..
  5. 사이트 모음 만들기 선택 후 사이트 이름, 설명 입력
  6. 서식 파일 선택에서 Enterprise –> My Site Host 선택
  7. 할당량 서식 파일에서 Personal Site 선택
  8. 다시 사이트 모음 만들기 선택 후 웹 사이트 주소의 관리 경로 정의 선택
  9. personal 와일드 카드 경로 추가
  10. 웹 응용 프로그램 관리에서 생성된 Web App 선택 후 리본 메뉴의 셀프 서비스 사이트 만들기 선택
  11. 셀프 서비스 사이트 만들기 사용 설정

 

이렇게 하면 일단 My Site를 사용하는 Web App 설정은 끝난 것입니다.

DNS 등록이나, 호스트 등록은 되어 있다고 생각하고 진행합니다

안되어 있는 경우 직접 등록해 주시기 바랍니다.

대채 엑세스 맵핑의 설정은 아래 사이트에서 확인하여 주시기 바랍니다.

2011/02/22 - [SharePoint 2010/Settings] - Sharepoint 2010 대체 액세스 매핑(Alternate Access Mappings)


이것을 다시 My Site에서 사용할 수 있도록 설정해 줘야 합니다.

설정 할 때 서비스를 그대로 사용하셔도 관계는 없을 것 같으나.. 저는 삭제 하고 서비스를 다시 만들고 진행하겠습니다.

방법은 아래와 같습니다.

  1. 중앙관리 –> 응용 프로그램 관리로 접속
  2. 서비스의 응용프로그램 –> 서비스 응용 프로그램 관리로 접속
  3. User Profile Service Application 선택 상단의 리본메뉴에서 삭제 클릭
  4. 리본 메뉴에서 새로 만들기 –> User Profile Service 응용프로그램 선택
  5. 이름 및 응용 프로그램 풀 이름 설정 (User Profile SVC, User Profile SVC Pool)
  6. 프로필 데이터베이스 등을 설정하고자 하면 이름 변경
  7. 내 사이트 호스트 URL, 내 사이트 관리 경로 입력 (생성한 Web App 경로 [http://my.dev.com/], /personal)
  8. 서비스 응용 프로그램 관리 재 접속 –> User Profile SVC 선택 후 리본 메뉴의 관리 선택
  9. 내 사이트 설정 –> 내 사이트 설정으로 접속
  10. 기본 설정 검색 센터 경로 설정, 언어 옵션 선택, Newsfeed 선택 후 완료.

 

이렇게 하면 완료 된 것입니다.

간단한게 설명만 해 놓았고 위의 설명대로만 따라 하시면 됩니다.

중요한 부분은 아래의 캡쳐를 확인해 주시고 직접 My Site로 접속해 보시면 됩니다.

 

신규 Web App 생성 시 설정 내용

 

my.dev.com의 사이트 모음 생성

 

my.dev.com의 personal 와이드 경로 추가

 

셀프 서비스 사이트 만들기

 

User Profile Service 삭제

 

User Profile 생성

 

User Profile 서비스 구성

 

내 사이트 설정

 

이렇게 해서 완성된 사이트는 아래와 같습니다.


이상입니다.


고맙습니다~



어제 오늘 삽질한 결과 결론은 Web Application Page에서는 안된다!! 라는 참혹한 결과를 얻었습니다.

Prefix의 경우 제가 하고자 하는 방식은 다음과 같습니다.

해당 Url에 Prefix가 있는지 검사해서. 없으면 만드는 아주 단순한 방식의 프로그래밍..

 

소스는 아래와 같습니다.

SPWebApplication webApp = SPWebApplication.Lookup(new Uri(strHostUrl));
SPPrefixCollection prefixColl = webApp.Prefixes;
if (prefixColl.Contains(txtSitePrefix.Text.Trim()) == false)
{
    SPPrefix newPrefix = webApp.Prefixes.Add(txtSitePrefix.Text.Trim(), SPPrefixType.ExplicitInclusion);
}

위의 코드 중 Prefixes.Add 시점에 “액세스가 거부되었습니다.”라는 오류가 발생됩니다.

 

그래서 좀 찾아보니. Microsoft.SharePoint.Administration.SPPersistedObject.BaseUpdate()에서 해당 에러를 반환합니다.

아래 이미지에 if문에서 else 구문으로 빠지는데 거기에 throw new SecurityException(SPResource.GetString("AccessDenied", new object[0]));

되어 있네요.. 흠…

 

이게 참 신기한 것이.. Feature로 만들면 잘 되는데.. 어플리케이션 페이지에서는 안됩니다.

 

그리고 또 하나 WebAppcliation.Features의 remove 또한 안됩니다.

 

그래서. 해결방법이 없다 입니다. ㅠ.ㅠ

누가 잘 하시는 분 이것 좀 해결 해 주세요!!

왜 안되는건지!! ㅠ.ㅠ

XmlDocument Transform의 경우에는 아래와 같이 하시면 됩니다.

2009/01/13 - [CSharp/Development] - Xml Xslt Transform with C#


요즘 XDocument를 많이 사용하고 있어서 Extensions 매소드로 따로 만들어 보았습니다.

별로 어려운 부분은 없으며, 그냥 아래 코드를 참고 하시면 될 것 같습니다.


Extension Method

public static class XDocExtensions
{
	#region // static string GetTransformation(this XDocument xDoc, string strXslPath) //
	/// <summary>
	/// XDocument에 Xsl를 트랜스포메이션 한 후 해당 데이터를 반환한다.
	/// </summary>
	/// <param name="xDoc">Xml Doc</param>
	/// <param name="strXslPath">Xsl Path</param>
	/// <returns>Transform Data</returns>
	public static string GetTransformation(this XDocument xDoc, string strXslPath)
	{
		string strResult = String.Empty;
		XslCompiledTransform xsl = new XslCompiledTransform(true);
		xsl.Load(strXslPath);

		using (var ms = new MemoryStream())
		{
			XmlWriterSettings settings = new XmlWriterSettings()
			{
				ConformanceLevel = ConformanceLevel.Auto
			};

			using (var writer = XmlWriter.Create(ms, settings))
			{
				xsl.Transform(xDoc.CreateReader(), writer);

				writer.Flush();
				ms.Position = 0;

				strResult = Encoding.UTF8.GetString(ms.GetBuffer());
			}
		}

		return strResult;
	}
	#endregion
}


아래는 해당 메소드 호출 부분입니다.

XDocument doc = new XDocument(
	new XElement("Roots",
		new XElement("Item", "1")
		, new XElement("Item", "2")));

string strTransformData = String.Empty;
strTransformData = doc.GetTransformation(Server.MapPath(strXslPath));

 

이상입니다.

감사합니다.


Download MSChart Control Tool

http://www.microsoft.com/ko-kr/download/details.aspx?id=14422

 

기본 .Net 의 경우에 Web.config 구성하는 방법

http://msdn.microsoft.com/ko-kr/library/dd990785(v=vs.100)

 

Sharepoint 사용시에 Web.config 설정을 하지 않으면 아래와 같이 오류가 발생됩니다.

오류 내용은 아래와 같습니다.

 

요청 형식 ‘GET’에 대한 HTTP 처리기가 없습니다.

 

아래와 같이 Web.config 파일을 구성하셔야 합니다.

<configuration>
   ...
   <system.web>
      ...
      <httpHandlers>
         ...
         <add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />
         ...
      </httpHandlers>
      ...
   </system.web>
   ...
  <system.webServer>
    ...
    <handlers>
      ...
      <add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      ...
    </handlers>
  ...
  </system.webServer>
  ...
  <appSettings>
    ...
    <add key="ChartImageHandler" value="storage=file;timeout=20;dir=c:\Temp\;"/>
    ...
  </appSettings>
</configuration>

 

그리고 IIS에 구성되어야 하는 부분이 있습니다.

appSettings에 설정한 dir 경로가 이미지 출력 경로입니다.

이 경로는 IIS에 가상경로로 설정해야 합니다.

 

 

그런 후 코드에서 ImageLocation을 해당 경로로 설정해 주셔야 합니다.

Chart chrtSalesData = new Chart();
chrtSalesData.ImageStorageMode = ImageStorageMode.UseImageLocation;

chrtSalesData.Legends.Add("Legend");
chrtSalesData.Width = 500;
chrtSalesData.Height = 300;
chrtSalesData.RenderType = RenderType.ImageTag;
string imagePath = "~/_layouts/ChartImg/";
chrtSalesData.ImageLocation = imagePath + "ChartPic_#SEQ(200,30)";
chrtSalesData.Palette = ChartColorPalette.Berry;

그런 후 해당 페이지를 보면 아래와 같이 정상적으로 이미지가 출력 되는 것을 확인 할 수 있습니다.

 

아래는 위의 이미지를 출력하는 코드입니다.

aspx, aspx.cs 코드 첨부하였습니다.

 

이상입니다.

감사합니다.


MSDN에 잘 나와 있는 내용입니다.

MSDN의 경로는 아래와 같습니다.

PIVOT 및 UNPIVOT 사용

피벗 변환

 

제가 만들고자 하는 내용은 아래와 같습니다.

데이터는 일자, 회사코드, 사용자 아이디 와 같은 경태로 입력됩니다.

이걸 일자에 회사코드 별 사용자 수를 출력하려고 합니다.

 

이럴 때 피벗을 이용하면 쉽게 해결 할 수 있는데요.

아래와 같은 모양을 두 번째 그림처럼 만들려고 합니다.

 

 

첫 번째 이미지의 코드는 아래와 같습니다.

SELECT CREATE_DAY, COMP_CODE, COUNT(USER_ID) AS USER_CNT
  FROM TB_VISITED_LOG
 WHERE COMP_CODE IS NOT NULL
 GROUP BY COMP_CODE, CREATE_DAY
 ORDER BY CREATE_DAY DESC

 

두 번째 이미지의 코드는 아래와 같습니다.

DECLARE @Prod varchar(2000)
SELECT	@Prod = ''
	
SELECT	@Prod = @Prod + '[' + COMP_CODE + '],'
  FROM	(SELECT Distinct COMP_CODE FROM TB_VISITED_LOG WHERE COMP_CODE IS NOT NULL) A
SELECT	@Prod = LEFT(@Prod, LEN(@Prod) - 1)

DECLARE	@NSQL	NVARCHAR(MAX)
SELECT	@NSQL	=  N'
SELECT CREATE_DAY, ' + @Prod + '
  FROM (
	SELECT CREATE_DAY, COMP_CODE, ISNULL(COUNT(USER_ID), 0) AS CNT
	  FROM TB_VISITED_LOG
	 WHERE COMP_CODE IS NOT NULL
	 GROUP BY CREATE_DAY, COMP_CODE
) T
 PIVOT (MAX(CNT) FOR COMP_CODE IN (' + @Prod + ')
) AS PVT
 ORDER BY CREATE_DAY DESC
'

PRINT @NSQL
EXECUTE dbo.SP_EXECUTESQL  @NSQL

 

위의 코드에 피벗 코드가 포함되어 있습니다.

현재 저는 Count 회사 사용자가 필요하여 PIVOT의 다음의 (MAX가 들어간 것이나 여기에 SUM, COUNT 등의 코드가 들어갈 수 있습니다.

좀 해 보시면 금방 이해 될 것입니다.

 

감사합니다.


 

페이스 북처럼 URL이 입력되면 하단부에 이미지와 해당 페이지의 제목을 가져오도록 만들어봤습니다…

 

실력이 형편없어서.. 엉성합니다.

완벽한 제품도 아니고요…

 

Textarea에 입력되는 키 값으로 처리해서.. 오류가 있습니다만… 그냥 이런식으로 한다라고 참고만 해 주십시오.

 

 


    plugin 부분의 스크립트입니다.

(function($) {
	$.fn.GetPageInfo = function(settings) {
		var config = {"widht": "100", "height": "200"};
		var UrlData = null;
		var Timer = null;

		if(settings) $.extend(config, settings);

		this.each(function(){
			jQuery.support.cors = true;
			if(this.tagName && this.tagName.toLowerCase() == "textarea"){
				var data = null;
				$(this).keyup(function(e){
					data = this.value;

					if(data.indexOf("http://") >= 0 && ValidURL(data)){
						if($("div#divLinker").length <= 0){
							$(this).after("<div id='divLinker'><img  id='imgLoading' src='http://jimpunk.net/Loading/wp-content/uploads/loading22.gif' alt='loading' />		<table id='tbContents' border='0' cellspacing='0' cellpadding='0' style='width:100%; display:none;'><tr>				<td width='120px'><img src='' border='0px' alt='' /></td>				<td>					<span class='' id='spanTitle'></span><br />					<span class='' id='spanBody'></span></td>			</tr>		</table></div>");
						}
						else{
							$("div#divLinker").css("display", "");
						}
						var url = null;

						if(data.indexOf("http://") == 0){
							switch(data.substr(data.length)){
								case " ":
									url = data.substr(0);
									break;
								case "\r":
									url = data.substr(0);
									break;
								default:
									url = data;
									break;
							}
						}
						else{
							url = data.substring(data.indexOf("http"), data.length);
						}
						
						if(UrlData != url){
							clearTimeout(Timer);

							UrlData = url;
							Timer = setTimeout(function(){
								fnAjaxCall();
							}, 1000);
						}
					}
				});
			}
		});

		function ValidURL(str) {
			var pattern = /(http|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/
			if(!pattern.test(str)) {
				return false;
			}
			else {
				return true;
			}
		}

		function fnAjaxCall(){
			var loading = $("div#divLinker img#imgLoading");
			var contentArea = $("div#divLinker table");

			loading.css("display", "");
			contentArea.css("display", "none");
			$.ajax({
				url: UrlData
				, async: false
				, contentType: "text/html; charset=UTF-8"
				, context: document.body
				, dataType: "html"
				, success: function(data, textStatus, jqXHR){
					$("div#divLinker img#imgLoading").css("display", "none");
					debugger;
					var linker = $(data);
					contentArea.css("display", "");

					var imgFirst = linker.find("img:first");
					if(imgFirst.width() > imgFirst.height())
						contentArea.find("img").width("100px");
					else
						contentArea.find("img").height("100px");
					
					if(imgFirst.length > 0){
						contentArea.find("img").css("display", "");
						contentArea.find("img").attr("src",imgFirst.attr("src"));
					}
					else
						contentArea.find("img").css("display", "none");

					contentArea.find("span#spanBody").text(data.match("<title>(.*?)</title>")[1]);
					contentArea.find("span#spanBody").text(linker.find("meta[name=description]").attr("content"));
				}
				, error: function(XMLHttpRequest, textStatus, errorThrown){
					$("div#divLinker").css("display", "none");
					alert(errorThrown);
				}
			});
		}

		return this;
	}
})(jQuery);

 

 


    Html 파일입니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title> new document </title>
		<meta name="generator" content="editplus">
		<meta name="author" content="angeleyes">
		<meta name="keywords" content="angeleyes,testhtml,testjavascript">
		<meta name="description" content="test document">
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=8" />

		<style type="text/css">

		</style>

		<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
		<script type="text/javascript" src="pageinfoplugin.js"></script>
		<!--script type="text/javascript" src="http://dev.sencha.com/deploy/dev/docs/resources/ext-base.js"></script>
		<script type="text/javascript" src="http://dev.sencha.com/deploy/dev/docs/resources/ext-all.js"></script-->

		<script language="javascript" type="text/javascript">
		//<![cdata[
			$(document).ready(function() {
				$("#txtData").GetPageInfo();
			});
			
			function fnFunction(){
				try {
					
				}
				catch(e) {
					alert("test ==> " + e.message);
				}
			}
		//]]>
		</script>
	</head>

	<body>
		<input type="text" id="txtText" value="" />
		<textarea id="txtData" rows="3" cols=""></textarea>
		<input type="button" id="btnButton" value="button" onclick="fnFunction();" />

	</body>
</html>

 

 

적용화면은 아래와 같습니다.

 

 

추후 Plugin 부분에서 텍스트 박스의 URL 체크 부분은 업데이트 하도록 하겠습니다.

 

그리고 아래 부분은 현재까지의 오류 현황입니다.

  • URL 다음에 작성된 텍스트가 있는 경우 URL 제대로 인식 못함
  • 이미지 교체 불가
  • loading 이미지 불완전
  • 본문의 text를 가져오지 못함..
  • 메타 태그의 description도 못 가져옴
  • https 구분 불가
  • 등 등 등 등….

 

오류 투성이입니다. *_*

 

PS. 혹시 괜찮은 스크립트 작성 툴 알고 계시면 추천 부탁 드립니다.

 

감사합니다.


+ Recent posts