Sitecore Experience Analytics Graphs Issue - sitecore

After upgrading my site from 7.1 to 8.1 I have the following error message appears when opneing any page in the expierence analytics:
"The 'Graph Name' graph cannot be displayed due to a server error. Contact you system administrator."
The following call show 500 error on the browser console:
"http://sitename/sitecore/api/ao/aggregates/all/DC0DB760B0F54690B9EB1BBF7A4F7BD1/all?&dateGrouping=collapsed&&keyTop=8&keyOrderBy=valuePerVisit-Desc&dateFrom=07-04-2016&dateTo=05-07-2016&keyGrouping=by-key"
I checked the log files and there is no server error logged there!
More information:
The error message:
"ValueFactory attempted to access the Value property of this instance."
Also
" at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.GetControllerMapping() at System.Web.Http.Routing.AttributeRoutingMapper.AddRouteEntries(SubRouteCollection collector, HttpConfiguration configuration, IInlineConstraintResolver constraintResolver, IDirectRouteProvider directRouteProvider) at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<>c__DisplayClass4.<MapAttributeRoutes>b__1() at System.Web.Http.Routing.RouteCollectionRoute.EnsureInitialized(Func`1 initializer) at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<MapAttributeRoutes>b__0(HttpConfiguration config) at System.Web.Http.HttpConfiguration.ApplyControllerSettings(HttpControllerSettings settings, HttpConfiguration configuration) at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type) at System.Web.Http.Controllers.HttpControllerDescriptor..ctor(HttpConfiguration configuration, String controllerName, Type controllerType) at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.InitializeControllerInfoCache() at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.GetControllerMapping() at System.Web.Http.Routing.AttributeRoutingMapper.AddRouteEntries(SubRouteCollection collector, HttpConfiguration configuration, IInlineConstraintResolver constraintResolver, IDirectRouteProvider directRouteProvider)
at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<>c__DisplayClass4.<MapAttributeRoutes>b__1() at System.Web.Http.Routing.RouteCollectionRoute.EnsureInitialized(Func`1 initializer) at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<MapAttributeRoutes>b__0(HttpConfiguration config) at
System.Web.Http.HttpConfiguration.ApplyControllerSettings(HttpControllerSettings settings, HttpConfiguration configuration) at
System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type) at
System.Web.Http.Controllers.HttpControllerDescriptor..ctor(HttpConfiguration configuration, String controllerName, Type controllerType) at
Sitecore.Services.Infrastructure.Web.Http.Dispatcher.NamespaceHttpControllerSelector.InitializeControllerDictionary() at System.Lazy`1.CreateValue()--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at Sitecore.Services.Infrastructure.Web.Http.Dispatcher.NamespaceHttpControllerSelector.FindMatchingController(String namespaceName, String controllerName) at Sitecore.Services.Infrastructure.Web.Http.Dispatcher.NamespaceHttpControllerSelector.SelectController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
Any ideas?

The cause of this error is you might be using Web Api in your code. To integrate web api with site core you need to extend your global.asax as below
public class GlobalExtended : Sitecore.Web.Application
{
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(ConfigureRoutes);
}
public static void ConfigureRoutes(HttpConfiguration config)
{
config.Routes.MapHttpRoute("DefaultApiRoute",
"api/{controller}/{action}/{id}",
new { id = RouteParameter.Optional });
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
}
}
You can go through below url for detailed explanation
https://sitecorecommerce.wordpress.com/2014/11/30/webapi-attribute-routing-is-not-working-with-sitecore-7-5/
http://blog.krusen.dk/web-api-attribute-routing-in-sitecore-7-5-and-later/

Sitecore support provided the cause and solution for this and thought will add it in case same issue happened with someone else:
Cause:
It looks like the issue is caused by a conflict in a Web API configuration
As far as I can see, the following code is executed during the application start:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
System.Web.Http.GlobalConfiguration.Configure(MyDll.WebApiConfig.Register);
}
Solution:
As an alternative approach, this code can be moved to the "initialize" pipeline to run on application startup.
In case if custom code is run after the default Sitecore.ExperienceAnalytics.Api.Pipelines.Initialize.WebApiInitializer processor, the Experience Analytics configuration will be loaded first.
For example:
1) Create the "initialize" pipeline processor
internal class WebApiInitializer
{
public void Process(PipelineArgs args)
{
System.Web.Http.GlobalConfiguration.Configure(Register);
}
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
}
}
2) Create a config file and place in into the Include/Z.MapRoutes fodler (so it will be loaded last):
<configuration xmlns:x="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="HttpAttributeRouting.WebApiInitializer, HttpAttributeRouting" x:after="processor[position()=last()]" />
</initialize>
</pipelines>
</sitecore>
</configuration>

Related

Calling a Spring Boot 2 REST service with multipart/form-data with Postman results in a EOFException

While working on a personal project on Spring Boot, I have to develop a web service that accepts a file and some metadata, and I have decided to test with a Postman client.
Versions I am using:
Postman version: Postman for Mac Version 7.8.0 OS X 18.7.0 / x64
Java version: 1.8.0_212
Spring boot version: 2.1.1.RELEASE
As metadata will potentially be quite structured, I have decided to use the multipart/form-data content type, consisting in two parts:
a "file" part containing the file
a "body" part containing the json with the metadata
I've configured the call in Postman like this
Now, Spring boot configuration. First of all, I've added the following lines to application.properties:
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=20MB
# Max Request Size
spring.servlet.multipart.max-request-size=25MB
I've then created my controller with the endpoint
#PostMapping(Paths.Registrations.BASE)
#ResponseBody
public PostRegistrationResponseDto postRegistration(#RequestParam("file") MultipartFile file, #RequestParam("body") PostRegistrationRequestDto req) {
PostRegistrationResponseDto resp = new PostRegistrationResponseDto();
resp.setId(new Random().nextLong());
resp.setFileName(req.getFileName());
resp.setRegistrationTime(LocalDateTime.now());
return resp;
}
Unfortunately, the call does not even arrive to Spring: I receive a HTTP 500 error with this body
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 500 – Internal Server Error</title>
<style type="text/css">
...
</style>
</head>
<body>
<h1>HTTP Status 500 – Internal Server Error</h1>
</body>
</html>
In my server log I get no exception, but when I set the debugger to block on exceptions I saw that tomcat launches an EOF exception with this stack trace
java.io.EOFException
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1208)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1142)
at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:729)
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:352)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:294)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
I admit I do not even know where to start from... can someone give me some hints of what I'm doing wrong?
Thanks :)
In the end, what I discovered is that Tomcat throws a lot of exceptions, not always meaningful.
The problem I had was not related to that exception, but to the fact that Spring doesn't automatically map the String part to the Dto.
To make everything work, I had to write this component:
package it.aegidea.proofy.api.converters;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.aegidea.proofy.api.dtos.proofyapi.PostRegistrationRequestDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.io.IOException;
#Component
public class PostRegistrationRequestDtoConverter implements Converter<String, PostRegistrationRequestDto> {
private final ObjectMapper objectMapper;
#Autowired
public PostRegistrationRequestDtoConverter(final ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
#Override
public PostRegistrationRequestDto convert(String source) {
try {
return objectMapper.readValue(source, PostRegistrationRequestDto.class);
} catch (IOException e) {
return null;
}
}
}
This way, Spring understood how to map the string to a PostRegistrationRequestDto and could successfully map the request to the types on the endpoint.

Sitecore publish pipeline, how to catch if publish failed to target Database

Issue: Unable to catch if publish item to TargetDatabase fails.
In sitecore UI, When I publish an item from master database to web database(Target Database), I wanted to check if publish was successful before it shows in UI.
looking at the following post from John West about the pipeline order:
http://www.sitecore.net/learn/blogs/technical-blogs/john-west-sitecore-blog/posts/2011/08/intercept-item-publishing-with-the-sitecore-aspnet-cms.aspx
I've added the following publish item processor:
<processor patch:after="*[#type='Sitecore.Publishing.Pipelines.PublishItem.PerformAction, Sitecore.Kernel']" type="BOTWLibrary.Pipelines.EvaluateResult, BOTWLibrary"/>
In EvaluateResult.cs
public class EvaluateResult : PublishItemProcessor
{
public override void Process(PublishItemContext context)
{
// check if publish was successful.
}
}
Thanks in advance.
If the publish fails it will set the results operation to none, as well as give a reason for the unknown publish action. This isn't a guarantee that the publish failed but I think it's the closest you'll get.
public class EvaluateResult : PublishItemProcessor
{
public override void Process(PublishItemContext context)
{
// check if publish was successful.
if(context.Result.Operation == PublishOperation.None)
{
throw new Exception(context.Result.Explanation);
}
}
}

Sitecore: DMS 7.1 Analytics is disabled

I am trying to get Sitecore DMS 7.1 working. I followed the instructions on the sitecore support pages. I triple checked all the steps referred to on this website.
https://www.sitecore.net/Learn/Blogs/Technical-Blogs/John-West-Sitecore-Blog/Posts/2011/08/Troubleshooting-Analytics-is-Disabled-with-the-Sitecore-Customer-Engagement-Platform.aspx#comments
I have looked in the log file and i am getting.
3112 10:20:35 ERROR Application error.
Exception: System.Web.HttpException
Message: Online Marketing Suite is not enabled
Source: mscorlib
Server stack trace:
at Sitecore.Analytics.Reports.ReportDataHandler.AssertState(HttpContext context)
at Sitecore.Analytics.Reports.ReportDataHandler.ProcessRequest(HttpContext context)
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase)
at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData)
at Sitecore.Analytics.Reports.ReportDataHandler.RequestProcessor.EndInvoke(IAsyncResult result)
at Sitecore.Analytics.Reports.ReportDataHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar)
Help. We have other sitecore sites and I was able to get it working on sitecore 7 platform.
Here is the logic that is causing the error to be thrown:
public static bool Enabled
{
get
{
if (Settings.GetBoolSetting("Analytics.Enabled", false))
return Sitecore.SecurityModel.License.License.HasModule("Sitecore.OMS");
else
return false;
}
}
So you can see that there are 2 criteria that need to be met.
First, the "Analytics.Enabled" setting in the analytics config file need to be set to true. It should look like the following.
<!--
ANALYTICS ENABLED
Determines whether analytics is enabled or not.
Default: true
-->
<setting name="Analytics.Enabled" value="true" />
Second, your license needs to include DMS (It's refers to it as "OMS" internally).
if (Context.Site.EnableAnalytics)
{
...
}

System.Security.SecurityException While calling web service in silverlight

I have created web service and i am calling from silverlight application.
I am getting Inner Exception like:
{System.Security.SecurityException ---> System.Security.SecurityException: Security error.
at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.BrowserHttpWebRequest.<>c_DisplayClassa.b_9(Object sendState)
at System.Net.Browser.AsyncHelper.<>c_DisplayClass4.b_0(Object sendState)
--- End of inner exception stack trace ---
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)}
Stack Trace :
" at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)\r\n at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)\r\n at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)\r\n at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)"
When I google this error :
I came to know that this is issue of cross domain url so i have to add clientaccesspolicy.xml and crossdomain.xml file under C:\inetpub\wwwroot.
still am getting same error:
Let me know how to fix this error.
Below code i have used:
System.Uri uri = new System.Uri("https://[localhost]/CustomerPortalService12/AddAccount/" + "AccountName");
var result = "";
try
{
var webClient = new WebClient();
webClient.DownloadStringCompleted +=webClient_DownloadStringCompleted;
webClient.DownloadStringAsync(uri);
}
catch (Exception ex)
{
var wtf = ex.Message;
}
}
}
void webClient_DownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e)
{
}
Make sure the clientaccesspolicy.xml contains the domain you are using in the browser. This maybe localhost if you're debugging locally. The clientaccesspolicy.xml must be at the root of the domain where the services is hosted. If you are hosting the service local as well as the Silverlight project then make sure the file is accessible from your bowser at http://localhost/clientaccesspolicy.xml or https://localhost/clientaccesspolicy.xml depending on how you are calling the service. Otherwise substitute localhost for the domain the service is on.
You clientaccesspolicy.xml should look something like:
<?xml version="1.0" encoding="UTF-8"?>
-<access-policy>
-<cross-domain-access>
<!--May have multiple elements-->
-<policy>
-<allow-from http-request-headers="*">
<domain uri="https://localhost"/>
</allow-from>
-<grant-to>
<resource include-subpaths="true" path="/"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

ServiceStack JsonServiceClient based test fails, but service works in browser

After I got my single-page web app working (web pages served with ServiceStack's RazorFormat() MVC, not .ASP MVC), I ran a (previously passing) test for the service. The test failed. Tested the web app again (debug run, navigate to //localhost:1337/ResourceList in the browser): still working. Is something wrong with my test?
Here's the error:
Test Name: TestResourceList
Test FullName: [0-1015]ServiceWrapper.Test.TestSWrapperServices.TestResourceList
Test Source: c:\Users\uname\Documents\Visual Studio 2012\Projects\ServiceWrapper\UnitTestProject1\ServiceTests.cs : line 96
Test Outcome: Failed
Test Duration: 0:00:02.188
Result Message:
System.Net.WebException : Unable to connect to the remote server
----> System.Net.Sockets.SocketException : No connection could be made because the target machine actively refused it 127.0.0.1:1337
Result StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Get[TResponse](IReturn`1 request)
at ServiceWrapper.Test.TestSWrapperServices.TestResourceList() in c:\Users\uname\Documents\Visual Studio 2012\Projects\ServiceWrapper\UnitTestProject1\ServiceTests.cs:line 98
--SocketException
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
Here's the test:
namespace ServiceWrapper.Test
{
[TestFixture]
public class TestSWrapperServices
{
AppHost appHost;
private const string ListeningOn = "http://*:1337/";
public const string Host = "http://localhost:1337";
private const string BaseUri = Host + "/";
[TestFixtureSetUp]
public void OnTestFixtureSetUp()
{
var appSettings = new AppSettings();
var username = Environment.GetEnvironmentVariable("USERNAME");
var userdomain = Environment.GetEnvironmentVariable("USERDOMAIN");
AppHost.AppConfig = new AppConfig(new AppSettings());
appHost = new AppHost();
// initialize Service Server
ServiceServer.SetUser(AppHost.AppConfig.UserName, AppHost.AppConfig.Password);
ServiceServer.SetLog(String.Empty);
try
{
appHost.Init();
appHost.Start(ListeningOn);
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode == 5)
{
System.Diagnostics.Debug.WriteLine("You need to run the following command (as admin):");
System.Diagnostics.Debug.WriteLine(" netsh http add urlacl url={0} user={1}\\{2} listen=yes",
ListeningOn, userdomain, username);
}
else
{
System.Diagnostics.Debug.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
}
}
[TestFixtureTearDown]
public void OnTestFixtureTearDown()
{
appHost.Dispose();
}
[Test]
public void TestResourceList()
{
JsonServiceClient client = new JsonServiceClient(BaseUri);
ResourceList response = client.Get(new ResourceList());
Assert.Contains("Some Value", response.property);
}
[Test]
}
}
I upgraded to the latest ServiceStack - 3.9.55, and it still didn't work. So, I started over again, sanity checking from the beginning. It turns out that the program.cs ListeningOn has http://*:1337/ while the nunit TestFixture ListeningOn was http://localhost:1337/
Checking urlacl (as admin) for http://localhost:1337/:
C:\Windows\system32>netsh http show urlacl url=http://localhost:1337/
URL Reservations:
-----------------
Checking urlacl (as admin) for http://*:1337/:
C:\Windows\system32>netsh http show urlacl url=http://*:1337/
URL Reservations:
-----------------
Reserved URL : http://*:1337/
User: DOMAIN\user
Listen: Yes
Delegate: No
SDDL: D:(A;;GX;;;S-1-5-21-2595267603-2801715271-1705165942-1002)
My earlier troubleshooting left the two projects with inconsistent ListeningOn values. Interestingly, using http://*:1337/ doesn't work as a wildcard url, as perhaps I had expected.
Here's a handy code snippet to help you build the add urlacl command. It also provides a useful (!) sanity check on the exact url you're listening on.
Console.WriteLine("You need to run the following command:");
Console.WriteLine(" netsh http add urlacl url={0} user={1}\\{2} listen=yes",
ListeningOn, userdomain, username);
--- Update ---
Upgrading ServiceStack eliminated the 'connection actively refused' error message. Once ListeningOn values were unified, the real
error message was exposed:
Result Message: ServiceStack.ServiceClient.Web.WebServiceException : Service Unavailable
Result StackTrace:
at ServiceStack.ServiceClient.Web.ServiceClientBase.ThrowWebServiceException[TResponse](Exception ex, String requestUri)
at ServiceStack.ServiceClient.Web.ServiceClientBase.ThrowResponseTypeException[TResponse](Object request, Exception ex, String requestUri)
at ServiceStack.ServiceClient.Web.ServiceClientBase.HandleResponseException[TResponse](Exception ex, Object request, String requestUri, Func`1 createWebRequest, Func`2 getResponse, TResponse& response)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Get[TResponse](IReturn`1 request)
at RemoteServerWrapper.Test.TestRSWrapperServices.TestDataList() in c:\Users\user\Documents\Visual Studio 2012\Projects\RemoteServerWrapper\UnitTestProject1\ServiceTests.cs:line 183
It's still obscure -- but at least it's not reporting something that's completely different from the real issue. So then I implemented trace in my app.config, like this:
<configuration>
<!-- ... other config settings ... -->
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
<add name="console"/>
</listeners>
</source>
<source name="System.Net.HttpListener">
<listeners>
<add name="System.Net"/>
<add name="console"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.HttpListener" value="Verbose"/>
</switches>
<sharedListeners>
<add name="console"
type="System.Diagnostics.ConsoleTraceListener"
initializeData="false"/>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
</configuration>
Which exposed a better error message:
ERROR: [::1]:1337 Request not found: /datarequest?DataKey=some_key&startDate=20130701&endDate=20130708
OK - now I have to pull in the servicestack sources so I can step through the code and figure out why I'm getting 'Not Found' in the test, when it works when I 'debug/run' and test via the browser. Turns out that RestHandler.FindMatchingRestPath(httpMethod, pathInfo, contentType) wasn't returning a match. Humm. Why is that? The AppHost is declared identically. So, what's different?
The rest services live in my project's main assembly. When run from 'debug/run' the default assembly has the services, and everything works. But when run from the test project, with the services assembly added as a reference, servicestack can't find them. They're not in the default location, relative to the test project. So I added an AppHost class at the top of my test file, rather than relying on the one from my program.cs, and declared it as follows:
public class RSWrapperServicesAppHostHttpListener
: AppHostHttpListenerBase
{
public RSWrapperServicesAppHostHttpListener()
: base("RSWrapper Services Tests", typeof(DataRequestService).Assembly) { }
// 'DataRequestService' is a random rest service class,
// defined in the referenced services assembly
}
Now ServiceStack is happy, and my tests work again.
How did they ever work? Originally everything was jumbled together all in one project. Once I separated things into separate assemblies, i.e. DTO, Services, Business Logic and Tests, I broke it. But since I was temporarily holding off on unit tests while getting the UI working, I didn't notice right away.