ไม่สามารถใช้วัตถุการสื่อสาร System.ServiceModel.Channels.ServiceChannel เพื่อการสื่อสารได้เนื่องจากอยู่ในสถานะ Faulted
เกิดข้อผิดพลาดอะไรขึ้นและฉันจะแก้ไขมันอย่างไร
ไม่สามารถใช้วัตถุการสื่อสาร System.ServiceModel.Channels.ServiceChannel เพื่อการสื่อสารได้เนื่องจากอยู่ในสถานะ Faulted
เกิดข้อผิดพลาดอะไรขึ้นและฉันจะแก้ไขมันอย่างไร
คำตอบ:
คุณได้รับข้อผิดพลาดนี้เนื่องจากคุณปล่อยให้ข้อยกเว้น. NET เกิดขึ้นที่ฝั่งเซิร์ฟเวอร์ของคุณและคุณไม่ได้ตรวจจับและจัดการและไม่ได้แปลงเป็นความผิดของ SOAP เช่นกัน
ตอนนี้เนื่องจากฝั่งเซิร์ฟเวอร์ "ระเบิด" ออกรันไทม์ WCF ได้ "ผิด" ช่องสัญญาณ - เช่นลิงก์การสื่อสารระหว่างลูกค้าและเซิร์ฟเวอร์ไม่สามารถใช้งานได้ - หลังจากทั้งหมดดูเหมือนว่าเซิร์ฟเวอร์ของคุณเพิ่งระเบิดดังนั้นคุณจึงไม่สามารถสื่อสารกับ มันอีกแล้ว
ดังนั้นสิ่งที่คุณต้องทำคือ:
มักจะจับและจัดการข้อผิดพลาดด้านเซิร์ฟเวอร์ของคุณ - ไม่ปล่อยให้ข้อยกเว้น .NET เดินทางจากเซิร์ฟเวอร์ไปยังลูกค้า - เสมอห่อเหล่านั้นเป็นความผิดพลาด SOAP ทำงานร่วมกัน ตรวจสอบส่วนต่อประสานWCF IErrorHandlerและติดตั้งบนฝั่งเซิร์ฟเวอร์
หากคุณกำลังจะส่งข้อความที่สองไปยังช่องของคุณจากลูกค้าตรวจสอบให้แน่ใจว่าช่องไม่ได้อยู่ในสถานะที่ผิด:
if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
{
// call service - everything's fine
}
else
{
// channel faulted - re-create your client and then try again
}
หากเป็นเช่นนั้นสิ่งที่คุณสามารถทำได้คือกำจัดและสร้างพร็อกซีฝั่งไคลเอ็นต์อีกครั้งจากนั้นลองอีกครั้ง
เพื่อป้องกันไม่ให้เซิร์ฟเวอร์ตกอยู่ในสถานะความผิดปกติคุณต้องตรวจสอบให้แน่ใจว่าไม่มีข้อยกเว้นที่ไม่สามารถจัดการได้ หาก WCF เห็นข้อยกเว้นที่ไม่คาดคิดจะไม่รับสายอีกต่อไป - ปลอดภัยไว้ก่อน
สองโอกาสที่จะหลีกเลี่ยงพฤติกรรมนี้:
ใช้ FaultException (อันนี้ไม่คาดคิดสำหรับ WCF ดังนั้น WCF รู้ว่าเซิร์ฟเวอร์ยังคงสถานะที่ถูกต้อง)
แทน
throw new Exception("Error xy in my function")
ใช้เสมอ
throw new FaultException("Error xy in my function")
บางทีคุณอาจลอง .. จับบล็อกทั้งหมดแล้วโยน FaultException ในทุกกรณีของข้อยกเว้น
try
{
... some code here
}
catch (Exception ex)
{
throw new FaultException(ex.Message)
}
บอก WCF ให้จัดการข้อยกเว้นทั้งหมดโดยใช้ Errorhandler สิ่งนี้สามารถทำได้หลายวิธีฉันเลือกแบบง่าย ๆ โดยใช้แอททริบิวต์:
สิ่งที่เราต้องทำเพิ่มเติมคือการใช้แอททริบิวต์[SvcErrorHandlerBehaviour]
ใน Service Implementation ที่ต้องการ
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace MainService.Services
{
/// <summary>
/// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
/// </summary>
public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ } //implementation not needed
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{ } //implementation not needed
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
if (channelDispatcher == null)
continue;
channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
}
}
}
public class SvcErrorHandler: IErrorHandler
{
public bool HandleError(Exception error)
{
//You can log th message if you want.
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
if (error is FaultException)
return;
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
msg = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
}
นี่เป็นตัวอย่างง่าย ๆ คุณสามารถดำลึกเข้าไปใน IErrorhandler ได้โดยไม่ต้องใช้ naked FaultException
แต่FaultException<>
เป็นชนิดที่ให้ข้อมูลเพิ่มเติมดูIErrorHandlerสำหรับตัวอย่างโดยละเอียด
ตามจริงถ้าไม่สำเร็จหลังจากทำตามคำแนะนำโดยmarc_sโปรดทราบว่าองค์ประกอบ <security> ในการกำหนดค่าการเชื่อมโยงเซิร์ฟเวอร์ (หรือขาดดังกล่าว) ใน web.config บนเซิร์ฟเวอร์อาจทำให้เกิดข้อยกเว้นนี้ ตัวอย่างเช่นเซิร์ฟเวอร์คาดว่าจะมีการMessage
รักษาความปลอดภัยระดับและไคลเอนต์มีการกำหนดค่าให้None
(หรือหากเซิร์ฟเวอร์ไม่ได้เป็นส่วนหนึ่งของโดเมน Active Directory แต่โฮสต์ลูกค้าระยะไกลคือ)
เคล็ดลับ: ในกรณีเช่นนี้แอปไคลเอนต์มักจะเรียกใช้เว็บเซอร์วิสได้ดีเมื่อดำเนินการโดยตรงบนเครื่องเซิร์ฟเวอร์ภายใต้บัญชีผู้ดูแลระบบในเซสชัน RDP
เมื่อต้องการวินิจฉัยปัญหานี้ให้เรียกใช้บริการภายใต้ดีบักเกอร์ Visual Studio ใช้เมนู: Debug | ข้อยกเว้นและระบุว่าคุณต้องการแตกเมื่อมีการโยนข้อยกเว้น
ข้อผิดพลาดเดิมที่ส่งออกไปจะมีข้อความแสดงข้อผิดพลาดที่ดีกว่า "..it อยู่ในสถานะ Faulted"
ตัวอย่างเช่นฉันได้รับข้อยกเว้นนี้จาก ServiceHost.Open () แต่เมื่อฉันตรวจพบข้อยกเว้นดั้งเดิมในเวลาที่มีการโยนข้อผิดพลาดคือ:
บริการ 'MyServiceName' มีจุดสิ้นสุดแอปพลิเคชันที่ไม่มีโครงสร้างพื้นฐาน อาจเป็นเพราะไม่พบไฟล์การกำหนดค่าสำหรับแอปพลิเคชันของคุณหรือเนื่องจากไม่มีองค์ประกอบบริการที่ตรงกับชื่อบริการที่สามารถพบได้ในไฟล์การกำหนดค่าหรือเนื่องจากไม่มีการกำหนดจุดสิ้นสุดในองค์ประกอบบริการ
แก้ไขข้อผิดพลาดการสะกดคำใน App.config แก้ปัญหาได้
ฉันมีปัญหาเดียวกันในขณะที่พยายามใช้จุดปลายบริการ net.tcp wcf ในบริการ http asmx
อย่างที่ฉันเห็นไม่มีใครเขียนคำตอบเฉพาะว่าทำไมปัญหานี้ถึงเกิดขึ้น แต่จะจัดการได้อย่างไรเท่านั้น
ฉันดิ้นรนกับมันหลายวันติดต่อกันและในที่สุดฉันก็พบว่าปัญหามาจากไหนในกรณีของฉัน
ตอนแรกฉันคิดว่าเมื่อคุณทำการอ้างอิงไปยังบริการไฟล์ config จะถูกกำหนดค่าเกี่ยวกับแท็กความปลอดภัยเช่นเดียวกับที่อยู่ในแหล่งที่มา แต่นั่นไม่ใช่กรณีและฉันควรดูแลด้วยตนเอง ในกรณีของฉันฉันมีเพียง
<netTcpBinding>
<binding name="NetTcpBinding_IAuthenticationLoggerService"
</binding>
</netTcpBinding>`
ต่อมาฉันเห็นว่าส่วนความปลอดภัยหายไปและควรมีลักษณะเช่นนี้
<netTcpBinding>
<binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
</netTcpBinding>
ปัญหาที่สองในกรณีของฉันคือการที่ฉันใช้transferMode="Streamed"
บริการ WCF ต้นทางของฉันและในไคลเอนต์ฉันไม่มีอะไรเฉพาะเกี่ยวกับมันซึ่งไม่ดีเพราะค่าเริ่มต้นtransferMode
คือBuffered
และเป็นสิ่งสำคัญทั้งที่แหล่งที่มาและลูกค้าที่จะกำหนดค่าในเดียวกัน ทาง
ฉันมีปัญหาอื่นที่ฉันไม่คิดว่าได้รับการกล่าวถึงในคำตอบอื่น ๆ
ฉันต้องบริการจุดปลายบนที่อยู่ tcp และพอร์ตเดียวกัน ในแอปตั้งค่าฉันลืมเพิ่มจุดปลายทั้งสองดังนั้นบริการจึงทำงานบนพอร์ตที่ถูกต้อง แต่มีส่วนต่อประสานบริการที่ไม่ถูกต้อง
หากคุณเห็นข้อความนี้ใน Debug จาก Visual Studio และโซลูชันมีโครงการ WCF จากนั้นเปิดการตั้งค่าโครงการ WCF นี้ -> ไปที่แท็บ "ตัวเลือก WCF" -> ปิด "เริ่ม WCF Service Host เมื่อทำการดีบั๊ก ... "
สำหรับฉันปัญหาเกิดจากไฟล์ปรับแต่งโดยอัตโนมัติโดยนำเข้า WSDL ฉันอัพเดตการโยงเป็นจาก basicHttpBinding เป็น customBinding การเพิ่มการจัดการข้อยกเว้นเพิ่มเติมไม่ได้ช่วยชี้เรื่องนี้
ก่อน
<basicHttpBinding>
<binding name="ServiceName">
<security mode="Transport" />
</binding>
</basicHttpBinding>`
หลังจาก
<customBinding>
<binding name="ServiceName">
<textMessageEncoding messageVersion="Soap12" />
<httpsTransport />
</binding>
</customBinding>`
ในกรณีของฉันเหตุผลบางข้อผิดพลาดที่ไม่สามารถโหลดได้ ฉันพบเกี่ยวกับเรื่องนี้จากตัวแสดงเหตุการณ์ภายใต้ระบบ:
เกิดข้อผิดพลาดร้ายแรงเมื่อพยายามเข้าถึงคีย์ส่วนตัวของข้อมูลรับรองเซิร์ฟเวอร์ TLS รหัสข้อผิดพลาดที่ส่งคืนจากโมดูลการเข้ารหัสคือ 0x8009030D สถานะข้อผิดพลาดภายในคือ 10001
ข้อผิดพลาดนี้สามารถถูกเรียกใช้โดยคอมพิวเตอร์ของคุณเองเช่นกันและไม่ใช่เพียงข้อยกเว้นที่ไม่สามารถจัดการได้ หากเซิร์ฟเวอร์ / คอมพิวเตอร์ของคุณมีเวลาหยุดทำงานนานเกินไปหลายนาทีเว็บเซอร์วิส. NET หลายแห่งจะปฏิเสธคำขอของคุณโดยมีข้อผิดพลาดที่ไม่สามารถจัดการได้ มันจัดการจากมุมมองของพวกเขา แต่ไม่สามารถจัดการได้จากจุดของคุณ ตรวจสอบเพื่อให้แน่ใจว่าเวลานาฬิกาของเซิร์ฟเวอร์การรับของคุณถูกต้อง หากจำเป็นต้องแก้ไขคุณจะต้องรีเซ็ตบริการหรือรีบูตก่อนที่ช่องจะเปิดใหม่
ฉันประสบปัญหานี้บนเซิร์ฟเวอร์ที่ไฟร์วอลล์บล็อกการอัปเดตเวลาอินเทอร์เน็ตและเซิร์ฟเวอร์หยุดทำงานด้วยสาเหตุบางประการ บริการเว็บบุคคลที่สาม. NET ทั้งหมดเกิดข้อผิดพลาดเนื่องจากพวกเขาปฏิเสธคำขอบริการเว็บ การขุดลงใน Event Viewer ช่วยระบุปัญหา แต่การปรับนาฬิกาแก้ไขได้ ข้อผิดพลาดเกิดขึ้นในตอนท้ายแม้ว่าเราจะได้รับข้อความแสดงข้อผิดพลาด Faulted State สำหรับการเรียกใช้บริการเว็บในอนาคต
เซิร์ฟเวอร์จะยกเลิกการเชื่อมต่อโดยอัตโนมัติซึ่งไม่ได้รับข้อความใด ๆ ในช่วงเวลาเท่ากับระยะหมดเวลาที่ได้รับ ( ค่าเริ่มต้นคือ 10 นาที ) นี่คือการลดขนาด DoS เพื่อป้องกันไม่ให้ไคลเอ็นต์บังคับให้เซิร์ฟเวอร์เปิดการเชื่อมต่อเป็นระยะเวลาไม่ จำกัด
เนื่องจากเซิร์ฟเวอร์ยกเลิกการเชื่อมต่อเนื่องจากไม่ได้ใช้งานไคลเอ็นต์จะได้รับข้อยกเว้นนี้
คุณสามารถควบคุมระยะเวลาที่เซิร์ฟเวอร์อนุญาตให้การเชื่อมต่อไม่มีการใช้งานก่อนที่จะยกเลิกโดยการกำหนดค่าการหมดเวลารับของการเชื่อมโยงของเซิร์ฟเวอร์ เครดิต: TRVishwanath - MSFT
ฉันรู้ว่านี่เป็นโพสต์เก่า แต่มีสิ่งหนึ่งที่ต้องระวังเมื่อคุณไม่สามารถเปลี่ยนการรักษาความปลอดภัยได้เพื่อให้แน่ใจว่าตั้งชื่อผู้ใช้และรหัสผ่านของคุณแล้ว
ฉันมีบริการที่มี authenticationMode เป็น UserNameOverTransport เมื่อไม่ได้ตั้งชื่อผู้ใช้และรหัสผ่านสำหรับไคลเอ็นต์บริการฉันจะได้รับข้อผิดพลาดนี้
สำหรับฉันมันเป็นปัญหาตัวโหลดบาลานซ์ / url บริการเว็บเบื้องหลัง balancer โหลดเรียกว่าบริการอื่นที่อยู่เบื้องหลัง balancer โหลดเดียวกันโดยใช้ URL loadbalancer.mycompany.com
แบบเต็มเช่น: ฉันเปลี่ยนเป็นบายพาสโหลดบาลานเซอร์เมื่อเรียกเซอร์วิสที่สองโดยใช้localhost.mycompany.com
แทน
ฉันคิดว่ามีปัญหาการอ้างอิงแบบวงกลมเกิดขึ้นกับ load balancer
ไม่ใช่วิธีการแก้ไขปัญหานี้ แต่ถ้าคุณพบข้อผิดพลาดข้างต้นกับ Ektron eSync อาจเป็นไปได้ว่าฐานข้อมูลของคุณมีพื้นที่ดิสก์ไม่เพียงพอ
แก้ไข: อันที่จริงนี่ไม่ใช่ปัญหาทั้งหมดของ Ektron eSync เท่านั้น สิ่งนี้อาจเกิดขึ้นกับบริการใด ๆ ที่สอบถามฐานข้อมูลแบบเต็ม
แก้ไข: พื้นที่ดิสก์ไม่เพียงพอหรือบล็อกการเข้าถึงไดเรกทอรีที่คุณต้องการจะทำให้เกิดปัญหานี้