Unit testing EntitySetController<TEntity, TKey>.Post

Topics: ASP.NET Web API
Jan 3, 2013 at 5:21 AM

I have no problems with any of the OData methods exposed by EntitySetController, except POST. I get an ArgumentNullException when unit testing this and it seems that everything has executed perfectly, but the problem comes when it tries to format the Url of the newly created entity. Is there something I need to setup in the fake controller that is needed for this?

Jan 3, 2013 at 6:42 PM

Could you post some code ? or share a repro ?

Jan 10, 2013 at 3:49 AM

I actually have a different problem, Post always has null for the parameter.  I have a WCF Data Service 5.2 Client that is able to generate the Client Proxies and perform GETs.  But when I try to create a new instance of an Entity, the Post method is receiving a NULL object.

Are there any requirements for my domain/model classes to be correctly deserialized and passed to this method?  Right now they're just POCO classes with Xml Serialization attributes (if that matters).

Coordinator
Jan 10, 2013 at 5:06 PM

nigelpage, can you actually post the stack trace for the exception you are seeing?

Daniel Roth

Jan 10, 2013 at 9:37 PM

Daniel,

The stack trace at the point of the exception is: -

   at System.Uri..ctor(String uriString)
   at System.Web.Http.OData.EntitySetController`2.Post(TEntity entity)
   at Roster.Cloud.Service.Tests.Controllers.StaffControllerTest.CreateNewStaffMember() in c:\ws\Roster.Cloud\Roster.Cloud.Service.Tests\Controllers\StaffControllerTest.cs:line 103

I'm happy to zip the code up and send it to you if you like?

Nigel

Coordinator
Jan 10, 2013 at 10:54 PM

The relevant code is here (for the RC): http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/f079d76e57b5#src/System.Web.Http.OData/OData/EntitySetController.cs

 response.Headers.Location = new Uri(Url.ODataLink(
                                                    Configuration.GetODataPathHandler(),
                                                    new EntitySetPathSegment(controllerName),
                                                    new KeyValuePathSegment(ODataUriUtils.ConvertToUriLiteral(GetKey(entity), ODataVersion.V3))));
           

I'm guessing the ODataLink generation is failing because the ODataPathHandler is not populated on the request.

This doesn't appear to be an issue in our latest bits. Do you want to try grabbing a nightly build?: http://aspnetwebstack.codeplex.com/wikipage?title=Use%20Nightly%20Builds.

Daniel Roth

Jan 11, 2013 at 9:46 PM

Daniel,

I tried the latest nightly build and after working out a couple of changes that you seem to have made, it works!

Just to be sure I've done the right thing, it seems that you've changed the EnableOData extension method to a Routes extension method called MapODataRoute. This seems to need the route name to be OData and you've swapped round the prefix and IEdmModel parameters. In addition, you seem to have changed the name of the server side paging QueryableAttribute parameter to PageSize.

If both of these assumptions are correct, I'm happy and very much looking forward to the RTM version - thanks:-)

Nigel Page

Coordinator
Jan 11, 2013 at 10:20 PM

>  it seems that you've changed the EnableOData extension method to a Routes extension method called MapODataRoute

Yup

> This seems to need the route name to be OData

You should be able to use whatever route name you want

> you seem to have changed the name of the server side paging QueryableAttribute parameter to PageSize

Yup

> I'm happy and very much looking forward to the RTM version

That's great to hear! Thanks for trying out our bits!

Daniel Roth

 

Jan 12, 2013 at 5:45 PM

Great, but it definitely seems to want the route name to be OData, otherwise you get: -

System.ArgumentException: A route named 'OData' could not be found in the route collection.
Parameter name: name
Result StackTrace: 
at System.Web.Http.HttpRouteCollection.GetVirtualPath(HttpRequestMessage request, String name, IDictionary`2 values)
   at System.Web.Http.Routing.UrlHelper.GetHttpRouteHelper(HttpRequestMessage request, String routeName, IDictionary`2 routeValues)
   at System.Web.Http.Routing.UrlHelper.Link(String routeName, IDictionary`2 routeValues)
   at System.Web.Http.ODataUrlHelperExtensions.ODataLink(UrlHelper urlHelper, String routeName, IODataPathHandler pathHandler, IList`1 segments)
   at System.Web.Http.ODataUrlHelperExtensions.ODataLink(UrlHelper urlHelper, IList`1 segments)
   at System.Web.Http.OData.EntitySetControllerHelpers.PostResponse[TEntity,TKey](ApiController controller, TEntity createdEntity, TKey entityKey)
   at System.Web.Http.OData.EntitySetController`2.Post(TEntity entity)
   at Roster.Cloud.Service.Tests.Controllers.StaffControllerTest.CreateNewStaffMember() in c:\ws\Roster.Cloud\Roster.Cloud.Service.Tests\Controllers\StaffControllerTest.cs:line 103
Coordinator
Jan 14, 2013 at 4:08 PM

That's odd . . . we should only try to use the default route name if the route name is not on the request. The route name should get populated on the request if you are using MapODataRoute to setup your routes. Can you show me your route configuration? Do you have any routes that are not setup using MapODataRoute?

Daniel Roth

Jan 14, 2013 at 5:14 PM

No worries. As this is a web site that has a visual component and an API, I use RegisterRoutes method in RouteConfig.cs: -

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}",
                defaults: new { controller = "Home", action = "Index" }
and Register method in WebApiConfig.cs: -
            config.EnableQuerySupport();

            config.Routes.MapODataRoute("OData", "api", ContextHelpers.GetEdmModel());
The ContextHelpers.GetEdmModel, just returns and IEdmModel.
Nigel Page
Coordinator
Jan 14, 2013 at 6:04 PM

OK, your routes look fine.

Can you zip up your code that reproduces the exception so that we can take a look?

Daniel Roth

Jan 18, 2013 at 6:44 AM

Sorry, been interstate for a few days. No problem, files are zipped up - where would you like them sent to? You can email me on nigelp@synteca.com.

Coordinator
Jan 29, 2013 at 12:10 AM

Sorry about the slow reply. Go ahead and create an issue on our Issue Tracker and attach the files to the issue.

Thanks!

Daniel Roth

Feb 7, 2013 at 7:55 AM
Sorry Dan, now I'm slow in responding! My repro is 31.8MB when the solution is zipped up, so I can't follow your instructions but would be happy to email it to you.