Показаны сообщения с ярлыком WCF. Показать все сообщения
Показаны сообщения с ярлыком WCF. Показать все сообщения

четверг, марта 25, 2010

Конфигурация WCF Service без app.config

Недавно столкнулся с такой задачей - потребовалось произвести настройку WCF службы напрямую из кода, т.е. без использования .config файла приложения. Потребовалось немало времени, чтобы выгуглить вменяемые примеры, потому ту часть решения, которая получилась у
меня, выкладываю сюда, надеюсь пригодится кому в качестве отправной точки...


Итак, исходный конфиг:

<system.servicemodel>
            <!--  диагностика - включим трассировку сообщений, который будут сохраняться в файлах, указанных листенерах -->
            <diagnostics>
              <messagelogging logmalformedmessages="true" logmessagesattransportlevel="true">
            </messagelogging>

            <behaviors>
              <servicebehaviors>
                <behavior name="SampleService.Behavior.Service">

                  <!--  отдаем пока исключение в процесс отдладки -->
                  <servicedebug includeexceptiondetailinfaults="true">

                  <!--  разрешаем сервису отдавтать описание - wsdl -->
                  <servicemetadata  httpgetenabled="true">

                </servicemetadata >
              </servicedebug>

            </behavior>

            <!--  привязки и их настройки  -->
            <bindings>
              <webhttpbinding>
                <binding name="SampleService.EndPointConfiguration.Web">
                         allowCookies="true"
                         closeTimeout="00:10:00"
                         openTimeout="00:10:00"
                         receiveTimeout="00:10:00"
                         sendTimeout="00:10:00"
                         bypassProxyOnLocal="false"
                         maxBufferPoolSize="10000000"
                         useDefaultWebProxy="true"
                         maxReceivedMessageSize="4096">
                  <security mode="None"></security>
                </binding>
              </webhttpbinding>
            </bindings>

            <services>
              <!--  указываем сервис  -->
              <service  name="SampleService">
                        behaviorConfiguration="SampleService.Behavior.Service">
                <endpoint address="http://127.0.0.1:9999/">
                                      binding="webHttpBinding"
                          behaviorConfiguration="SampleService.Behavior.EndPointBehavior"
                                      bindingConfiguration="SampleService.EndPointConfiguration.Web"
                                      contract="SampleService.IServiceContract">
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
                <host>
                  <baseaddresses>
                    <add baseaddress="http://127.0.0.1:9999/">
                  </add>
                </baseaddresses>
              </host>
            </endpoint>


          </service >
</system.servicemodel>


превращается в пару строку из ini файла:

[sample_service]
host=127.0.0.1
port=9999 

c# код программного создания конечной точки и описанных поведений, аналогичных тем, которые были ранее в .config, приведен ниже:

            #region binding
            WebHttpBinding  binding = new WebHttpBinding();
            binding.AllowCookies = true;
            
            binding.CloseTimeout = TimeSpan.FromMinutes(10);
            binding.SendTimeout = TimeSpan.FromMinutes( 10 );
            binding.OpenTimeout = TimeSpan.FromMinutes( 10 );
            binding.ReceiveTimeout = TimeSpan.FromMinutes( 10 );

            binding.BypassProxyOnLocal = false;
            binding.UseDefaultWebProxy = true;
            
            binding.MaxBufferPoolSize = 1000000;
            binding.MaxReceivedMessageSize = 1000000;

            binding.Security.Mode = WebHttpSecurityMode.None;
            #endregion

            #region endpoint adress
            
            Uri endpointUri = GlobalConfiguration.SETTINGS_SAMPLE_SERVICE_BASE_ADDRESS;
            Uri mexEndpointUri = new Uri(String.Format("{0}/mex", endpointUri.ToString()));
            #endregion

            SampleServiceHost.Instance = new ServiceHost(typeof(SampleService), endpointUri);

            #region wcf behaviour setup

            //  behoviours
            SampleServiceHost.Instance.Description.Behaviors.Clear();

            ServiceBehaviorAttribute behaviour = new ServiceBehaviorAttribute();
            behaviour.InstanceContextMode = InstanceContextMode.Single;
            behaviour.ConcurrencyMode = ConcurrencyMode.Single;

            SampleServiceHost.Instance.Description.Behaviors.Add(behaviour);


            ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior();
            serviceMetadataBehavior.HttpGetEnabled = true;
            SampleServiceHost.Instance.Description.Behaviors.Add(serviceMetadataBehavior);


            ServiceDebugBehavior serviceDebugBehavior = new ServiceDebugBehavior();
            serviceDebugBehavior.HttpHelpPageEnabled = true;
            serviceDebugBehavior.HttpsHelpPageEnabled = true;
            serviceDebugBehavior.IncludeExceptionDetailInFaults = true;
            SampleServiceHost.Instance.Description.Behaviors.Add(serviceDebugBehavior);


            #endregion

            
            //  listening end point
            SampleServiceHost.Instance.AddServiceEndpoint(typeof(SampleService.IServiceContract), binding, endpointUri.ToString()).Behaviors.Add(new WebHttpBehavior());
            //  and mex endpoint
            SampleServiceHost.Instance.AddServiceEndpoint(typeof(IMetadataExchange), binding, mexEndpointUri.ToString());

            //  start service
            SampleServiceHost.Instance.Open();


понедельник, июля 21, 2008

WCF-service installation on IIS|ASP.NET

Столкнулся с такой проблемой: после перестановки iis и перерегистрации asp.net перестала работать wcf инфраструктура, точнее, на все запросы операций wcf-сервиса, который хостился под iis, всегда получал 404.3;

Решение в перерегистрации самого wcf (правда, я все равно до конца так и не понял, почему wcf, изначально установленный в процессе инсталляции .net 3.5, упал после перестановки iis, возможно все вдело в кривизне моих рук)..

Проблема и решение было найдено на:
http://blogs.msdn.com/davidwaddleton/archive/2007/11/02/wcf-and-404-3-errors.aspx



kept getting 404.3 errors, so I started examining IIS to make sure that the right
stuff is registered. After not finding anything wrong, I started looking at the WCF
installation. I found that my WCF services where not installed. You can do the
installation manually by running "ServiceModelReg.exe", which was found at
%Windows%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\.




Сам процесс перерегистрации:

Проверить статус wcf:
serviceModelReg -vi


Если получим сообщение "Default Installation" - wcf установлен, иначе, требуется перестановка wcf;

Инсталляция WCF:
serviceModelReg -i


как результат, установленный под iis инфраструктура wcf;


пятница, июля 18, 2008

An error occurred creating the configuration section handler for system.serviceModel/behaviors

При очередной выкладке wcf-сервиса в рамках нашего проекта стало возникать исключение следующего плана:



Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element 'authorizationBehavior' cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions.
Parameter name: element

Source Error:


Line 449:













Проблема в том, что наш Extension element -> 'authorizationBehavior' является объектом указанного через атрибут Type типа, а именно:








решением проблемы является указания full qualified name для сборки, т.е. требуется указывать номер версии, токен и культуру:









это конечно не есть хорошо (теперь при каждлой новой выкладке нужно уточнять номер версии), но другого вариант пока нет, причем такой баг был выялен только при переходе на новую development system, что удивительно потому что на старой системе такого не наблюдалось...

проблема описана здесь:
http://nayyeri.net/blog/configuration-error-for-custom-behavior-extensions-in-wcf/
https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=216431

четверг, июля 17, 2008

This message cannot support the operation because it has been copied

Собственно, возникла такая нехорошая проблема при разработке собственного message inspector, при очередной попытке прочитать body у message пришлось натолкнуться...

Проблема и ее решение описаны на официальном сайте команды разработки wcf:


http://wcf.netfx3.com/blogs/wcf_team_bloggers/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx
http://blogs.msdn.com/drnick/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx



можно привести кусок кода в моем случае:

protected override Message OnAfterReceivedRequest(string authToken, Message request)
{

// проблема описана в WCF
// http://wcf.netfx3.com/blogs/wcf_team_bloggers/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx
// http://blogs.msdn.com/drnick/archive/2006/07/26/This-message-cannot-support-the-operation-because-it-has-been-copied.aspx
// This message cannot support the operation because it has been copied
// This message cannot support the operation because it has been readed

MessageBuffer buffer = request.CreateBufferedCopy(int.MaxValue);
Message returnMessage = buffer.CreateMessage();
string parameters = buffer.CreateMessage().GetReaderAtBodyContents().ReadInnerXml();
buffer.Close();


string action = request.Headers.Action;
AuthorizationManager.RegistryOperationInvocation(authToken, action, parameters);

return returnMessage;
}



т.е. суть решения сводится к тому, чтобы работать каждый раз с копией message, а не с самим сообщением...

понедельник, марта 17, 2008

The target assembly contains no service types

В прокте используется WCF, причем сами контракты определены в одной сборке (Project.Services.Library as example), а реализации сервисов в другой (Project.Services.MyService as example), а хостились сервисы под asp.net - т.е. наружу выставлял из проекта (Project.Site) только .svc файл...

Вот........:) Cобственно, стала возникать такая проблема, при старте Project.Site (asp.net application) стало возникать сообщение в модальном диалоге:


The target assembly contains no service types

причем появились жуткие тормоза, что не особенно доставляло радости к процессу отладки и так без того досточного тяжелого asp.net приложения...

Решение, по крайне мере, для моего тяжелого случая, оказалось на
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2687265&SiteID=1


если коротко, из файла проекта с*.csproj определением контракта wcf-сервиса нужно просто удалить следующую строку:
<projecttypeguids>{3D9AD99F-2412-4246-B90B-4EAA41C64699};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</projecttypeguids>>






понедельник, марта 03, 2008

This collection already contains an address with scheme http.

При очередной выкладке одного из WCF сервисов возникла проблема с настройкой сервиса на продакшн-сервере, получаем постоянно исключение следующего вида (уточнение, сам сервис хостился в среде asp.net в web приложении на iis, доступном сразу по нескольким хостам, приложение по сути является порталом, хостящим разные сайты):



This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
Parameter name: item


Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
Parameter name: item



решение:

Данная ситуация случается в том случае, когда wcf-сервис может быть достугнут сразу по нескольким адресам....т.е. в нашем случае важно было указать из всех доступных хостов по указанному ip-адресу, на котором хостился web - сервис, только один в разрезе различных доступных binding-протоколов, как показано ниже в примере:


ссылки по теме:
http://blogs.msdn.com/rampo/archive/2008/02/11/how-can-wcf-support-multiple-iis-binding-specified-per-site.aspx



How can WCF support multiple IIS Binding specified per site ?


Background

IIS has web sites, which are containers for virtual applications which contain virtual directories. The application in a site can be accessed through one or more IIS binding.

IIS bindings provide two pieces of information – binding protocol and binding information. Binding protocol defines the scheme over which communication occurs, and binding information is the information used to access the site.

Example

Binding protocol – HTTP

Binding Information – IPAddress , Port, Hostheader

IIS supports specifying multiple IIS bindings per site, which results in multiple base addresses per scheme. A WCF service hosted under a site allows binding to only one baseAddress per scheme.



Solution in .Net Fx 3.0:Supporting Multiple IIS Bindings Per Site

Solution in .Net Fx3.5: BaseAddressPrefixFilters





Specifying a prefix filter at the appdomain level via config allows for filtering out unnecessary schemes. The incoming base addresses, supplied by IIS, are filtered based on the optional prefix list filter. By default, when prefix is not specified all addresses are passed through. Specifying the prefix will result in only the matching base address for that scheme to be passed through.


Example


   <system.serviceModel>

<serviceHostingEnvironment>

<baseAddressPrefixFilters>

<add prefix=”net.tcp://payroll.myorg.com:8000”/>

<add prefix=”http://shipping.myorg.com:9000”/>

</baseAddressPrefixFilters>

</serviceHostingEnvironment>

</system.serviceModel>





In the above example, net.tcp://payroll.myorg.com:8000 and http://shipping.myorg.com:9000 are the only base addresses, for their respective schemes, which will be allowed to be passed through. The baseAddressPrefixFilter does not support any wildcards .

The baseAddresses supplied by IIS may have addresses bound to other schemes not present in baseAddressPrefixFilter list. These addresses will not be filtered out.



ссылки по теме:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=373333&SiteID=1
http://www.robzelt.com/blog/2007/01/24/WCF+This+Collection+Already+Contains+An+Address+With+Scheme+Http.aspx
http://www.bokebb.com/dev/english/2047/posts/204720109.shtml