.Net Framework Standard

[C#] WebService .asmx 오류 전역 (예외)처리

달빛에취하다 2019. 6. 17. 17:19

SoapExtension을 상속받아 오류를 전역 단에서 예외처리 하는 부분입니다.

WebService 2.0 인 .asmx는 http 500 에러가 발생할 경우 Global.aspx의 Application_Error 에서 캡쳐가 선행되지 않고 클라이언트로 내려 갑니다.

가끔 보안상의 이유로 오류 세부 내용을 감춰야 하는 등의 처리나 별도 로그를 남기기 위해 사용됩니다.

 

※ SoapExceptionHandler.cs

    public class SoapExceptionHandler : SoapExtension
	{
		Stream _oldStream;
		Stream _newStream;

		public override Stream ChainStream(Stream stream)
		{
			_oldStream = stream;
			_newStream = new MemoryStream();
			return _newStream;
		}

		public override void ProcessMessage(SoapMessage message)
		{
			if (message.Stage == SoapMessageStage.AfterSerialize)
			{
				_newStream.Position = 0;

				if (message.Exception != null && message.Exception.InnerException != null)
				{
					// 오류가 있을경우
					InsertDetailExceptionStream(message.Exception.InnerException);
				}
				else
				{
					CopyStream(_newStream, _oldStream);
				}
			}
			else if (message.Stage == SoapMessageStage.BeforeDeserialize)
			{
				CopyStream(_oldStream, _newStream);
				_newStream.Position = 0;
			}
		}

		private void CopyStream(Stream from, Stream to)
		{
			TextReader reader = new StreamReader(from);
			TextWriter writer = new StreamWriter(to);
			writer.WriteLine(reader.ReadToEnd());
			writer.Flush();
		}

		private void InsertDetailExceptionStream(Exception exception)
		{
			XmlDocument doc = new XmlDocument();
			doc.Load(_newStream);
			
			XmlNode faultstringNode = doc.SelectSingleNode("//faultstring");
			faultstringNode.InnerText = "오류 입니다.~!";
			
			XmlNode detail = doc.SelectSingleNode("//detail");
			detail.InnerText = "오류 세부 내용 입니다.";


			XmlWriter writer = new XmlTextWriter(_oldStream, Encoding.UTF8);
			doc.WriteTo(writer);
			writer.Flush();
		}

		#region Not Used
		public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
		{
			return null;
		}

		public override object GetInitializer(Type serviceType)
		{
			return null;
		}

		public override void Initialize(object initializer)
		{
		}
		#endregion
	}

※ ExceptionHandlingAttribute.cs

	[AttributeUsage(AttributeTargets.Method)]
	public class ExceptionHandlingAttribute : SoapExtensionAttribute
	{
		public override Type ExtensionType { get { return typeof(SoapExceptionHandler); } }
		public override int Priority { get { return 0; } set { } }
	}

 

※ 사용방법

        [ExceptionHandling] //Attribute 로 사용
        [WebMethod(EnableSession = true)]
        public byte[] GetLog()
        {
            if (isSession())
            {
                return Compress.DataSet(Log.Log.GetLog());
            }

            return null;
        }

        [ExceptionHandling] //Attribute 로 사용
        [WebMethod(EnableSession = true)]
        public bool SetLog(string value1, string value2, string value3, string value4, string value5, string value6, string value7)
        {
            if (isSession())
            {
                return Log.Log.SetLog(value1.Decrypt(), value2.Decrypt(), value3.Decrypt(), value4.Decrypt(), value5.Decrypt(), value6.Decrypt(), value7.Decrypt());
            }
            else
            {
                return false;
            }

        }

 

 

출처 - https://haacked.com/archive/2005/06/29/ExceptionInjectionUsingCustomSoapExtension.aspx/