Witam ! Potrzebuję napisać usługę w wcf, która przyjmie od zewnętrznej aplikacji plik i zapisze go u siebie na dysku. Inne metody działają okej, ale gdy chcę przesłać plik do wcf otrzymuję : Serwer zdalny zwrócił nieoczekiwaną odpowiedź: (400) Bad Request. i niestety mimo moich kombinacji nie mogę sobie z tym problemem poradzić :/
Ogólnie, to mam metodę, która prezentuje się następująco
public void AddPhoto(uint userID, UploadFile file)
{
#region fileUpload
string guid = Guid.NewGuid().ToString().Replace("-", "");
string newFileName = guid + file.GetExtention();
if (file.GetExtention() == ".jpg" || file.GetExtention() == ".jpeg" || file.GetExtention() == ".png" || file.GetExtention() == ".gif")
{
if (!File.Exists(@"E:\uploads\"+ newFileName))
{
using (FileStream fs = new FileStream(@"E:\uploads\" + newFileName, FileMode.Create))
{
fs.Write(file.File, 0, file.File.Length);
fs.Close();
}
}
}
#endregion
PhotoData photoData = new PhotoData
{
Title = file.Title,
Description = file.Description,
userID = userID,
Path = @"E:\uploads\" + newFileName
};
entity.AddPhoto(photoData);
}
klasa upload file prezentuje się następująco :
[DataContract]
public class UploadFile
{
[DataMember]
public string FileName { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public byte[] File { get; set; }
public string GetExtention()
{
if (!string.IsNullOrEmpty(FileName))
{
return Path.GetExtension(FileName);
}
else return null;
}
public string GetFileNameWithoutExtention()
{
if (!string.IsNullOrEmpty(FileName))
{
return Path.GetFileNameWithoutExtension(FileName);
}
else return null;
}
}
Zaś w taki sposób przesyłam dane od klienta na serwer :
GalleryClient proxy = new GalleryClient();
UploadFile uploadFile = new UploadFile();
using (FileStream fs = new FileStream(@"C:\stone.jpg", FileMode.Open, FileAccess.Read))
{
byte[] buffor = new byte[fs.Length];
fs.Read(buffor, 0, (int)fs.Length);
fs.Close();
uploadFile.File = buffor;
}
// parę linijek nieważnych, przypisanie stringów itd
proxy.AddPhoto(1, uploadFile);
Do tego etapu wszystko jest ok, w obiekcie uploadFile -> tablicy byte[] File znajduje się 194233 elementów. I w tym momencie pojawia się exception który wskazuje na proxy.AddPhoto(), myślę spoko ;) Każdy normalny człowiek pomyśli, że po prostu długość przesyłanej wiadomości jest zbyt długi, ja też na to wpadłem ,poszperałem trochę i zmieniłem oby dwa pliki konfiguracyjne, teraz wyglądają tak :
config serwera :
<?xml version="1.0"?>
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "e:\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
<connectionStrings>
<add name="MySQL" connectionString="Server=localhost;Database=gallery;Uid=root;Pwd=admin1;" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WCFGallery.GalleryService">
<endpoint address="" binding="basicHttpBinding" contract="WCFGallery.IGallery" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="default" maxReceivedMessageSize="40000000">
<readerQuotas maxStringContentLength="5000000" maxArrayLength="5000000" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="500000"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
oraz config aplikacji klienckiej
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:57609/GalleryService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGallery"
contract="ServiceReference1.IGallery" name="BasicHttpBinding_IGallery" behaviorConfiguration="bigMessage"/>
</client>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IGallery" closeTimeout="00:05:00"
openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="40000000" maxBufferPoolSize="524288" maxReceivedMessageSize="40000000"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="bigMessage">
<dataContractSerializer maxItemsInObjectGraph="500000"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Jako, że to moje pierwsze spotkanie z WCF, nie wiem czy pliki konfiguracyjne są dobrze zbudowane, ale po prostu configi są przeklejone z wyników google. Niestety błąd cały czas występował, po długiej zabawie nie mogąc znaleźć błędu, przebłysk - włącz traceowanie aplikacji. Otrzymałem kod błędu który przedstawia się następująco :
<ExceptionString>System.ServiceModel.ProtocolException: The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.</ExceptionString>
Jednakże zarówno w aplikacji klienckiej jak i aplikacji serwerowej mam umieszczony wpis odnośnie MaxReceivedMessageSize