CreateResponse method in asp.net Web API - asp.net-web-api

calling this method:
public HttpResponseMessage PostProduct(Product item)
{
item = repository.Add(item);
var response = this.Request.CreateResponse<Product>CreateResponse(HttpStatusCode.Created, item);
string uri = Url.RouteUrl("DefaultApi", new { id = item.Id });
response.Headers.Location = new Uri(uri);
return response;
}
Is causing a compile-time error:
'System.Web.HttpRequestBase' does not contain a definition for 'CreateResponse' and the
best extension method overload 'System.Net.Http.HttpRequestMessageExtensions.CreateResponse<T>
(System.Net.Http.HttpRequestMessage, System.Net.HttpStatusCode, T)' has some invalid arguments.
What am I missing here?

The runtime type of item is probably not an instance of Product. You should be able to do this:
var response = Request.CreateResponse(HttpStatusCode.Created, item);
Even if item was an instance of Product, the generic <Product> argument is redundant and not necessary. If you used ReSharper, it would tell you that the "(Generic) Type argument specification is redundant".
Update
Does your class extend from Controller or ApiController? The error should be 'System.Net.Http.HttpRequestMessage' does not contain a definition for..., not 'System.Web.HttpRequestBase' does not contain a definition for....
WebApi controllers should extend from ApiController, not Controller. In an MVC controller, this.Request points to an instance of System.Web.HttpRequestBase. In a WebAPI controller, this.Request points to an instance of System.Net.Http.HttpRequestMessage.

CreateResponse is an extension method defined in System.Net.Http namespace.
Make sure to add a reference to System.Net.Http and System.Net.Http.Formatting in your project and add a correct using directive:
C#:
using System.Net.Http;
VB:
Import System.Net.Http

Related

When I set the CanonicalKey or CanonicalUrl for a dynamic node, I get a NullReferenceException

I'm using MVCSiteMapProvider v4.6.22 and have a dynamic node provider for one of my controllers.
Something like:
public class ProviderDetailsNodeProvider : DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
foreach (var provider in providers)
{
var dn = new DynamicNode()
{
Title = provider.Name,
ParentKey = "ParentKey",
Key = $"provider_master_{provider.ID}",
CanonicalUrl = "/url/something"
};
dn.RouteValues.Add("myRouteParamName", "myRouteParamValue");
yield return dn;
}
}
}
Without setting the CanonicalKey or CanonicalUrl properties of the DynamicNode, I get the correct behaviour. However I now wish to have multiple URLs pointing at the same content so I need to utilise the Canonical URL features of MVCSiteMapProvider.
If I attempt to set the CanonicalUrl as in the above snippet, or the CanonicalKey (my preferred choice), then when I attempt to use the helper methods, such as:
#Html.MvcSiteMap().SiteMapPath()
I get a NullReferenceException - it's the #Html.MvcSiteMap() which returns null.
What am I doing incorrectly, why do I get this NullReferenceException just by setting these properties against my dynamic nodes?
I'm using the MvcSiteMapProvider.MVC5 package, in an MVC6 application. I can't see a newer version on Nuget.
MVC 6 is not yet supported, as per the issue on NuGet.

RazorEngine WebApiTemplateBase #Url.Content()

How can I get #Url.Content() working in my _Layout.cshtml when RazorEngine is being used from ASP.NET Web API?
RazorEngine (v.3.7.2) only deals with the Razor syntax and not the additional helper methods like #Html or #Url. These can be added by extending the TemplateBase<> and setting it in the configuration.
There are code examples in some old issues: #26, #29; in an unreleased, incomplete piece of code in MvcTemplateBase.cs; and in the documentation for Extending the Template Syntax.
My problem is I'm using ASP.NET Web API (v.1) which won't have HttpContext.Current (nor should it). I want to provide a UrlHelper as I want to use its Content() method but it needs to be instantiated with the HttpRequestMessage which won't be available.
Perhaps there's no way to get #Url helper methods for my compiled layout. Perhaps I need some other way of getting the absolute path from the virtual path. It seems I'd still need some way of checking the Request though.
A way to get this working is to follow the direction set by Extending the Template Syntax and use VirtualPathUtility.ToAbsolute() in a helper method.
using System.Web;
using RazorEngine.Templating;
namespace MyNamespace.Web
{
public abstract class WebApiTemplateBase<T> : TemplateBase<T>
{
protected WebApiTemplateBase()
{
Url = new UrlHelper();
}
public UrlHelper Url;
}
public class UrlHelper
{
public string Content(string content)
{
return VirtualPathUtility.ToAbsolute(content);
}
}
}
Set up the TemplateService configuration with this extension of the TemplateBase<>.
var config =
new RazorEngine.Configuration.TemplateServiceConfiguration
{
TemplateManager = new TemplateManager(),
BaseTemplateType = typeof(WebApiTemplateBase<>)
};

How to send a List<object> to a Web Method?

I am developing a web application using MVC 3 and ASMX Web Services.
I am trying to send a List< object > to a Web Method, but I get the following error:
" cannot convert from 'System.Collections.Generic.List' to 'WebServiceClass.ArrayOfAnyType' "
This is my Web Service definition:
public class WebServiceClass : System.Web.Services.WebService
{
[WebMethod]
public bool MyWebMethod(List<object> ParameterValues)
{
//do stuff..
}
}
And this is the block of code where I call the Web Method:
List<object> ParameterValues = new List<object>();
WebServiceClass.WebServiceClassSoapClient MyWebService = new WebServiceClass.WebServiceClassSoapClient();
//I use actual objects here, this is just for an example
ParameterValues.Add(new DateTime(2012,5,2));
ParameterValues.Add(23);
ParameterValues.Add("some string");
MyWebService.MyWebMethod(ParameterValues);
My idea was to save time and pass Lists of objects to all Web Methods instead of defining WebMethod(DateTime date, int someint, string somestring).
Is there a solution for this?
Best regards.
If your method expects 3 parameters of type DateTime, int, and string than define a method with this arguments. Otherwise you will have to case down and your solution is not type-safe.
Are all your methods in code taking a list of objects as a parameter? Probably not. And the same should apply to web methods.

ASP.NET MVC 3 Dependency Injection - Controllers, Views & Action Filters

I'm trying to get dependency injection working in an ASP.NET MVC 3 application using Microsoft Unity. First i have implemented my own IDependencyResolver and activated it in my Global.asax file like so:
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
I found that i don't need to do anything else to get controller injection (via both the constructor and [Dependency] attribute) to work. With the default view engine i also found i could get the [Dependency] attribute to work in the standard views but not the Layout views. Is it possible to get this to work for the Layout Views aswell?
However i have implemented my own view engine which inherits from VirtualPathProviderViewEngine that overrides the CreateView/CreatePartialView methods and returns my own custom view (implements IView). See the Render method of the custom view below:
public void Render(ViewContext viewContext, TextWriter writer) {
var webViewPage = DependencyResolver.Current.GetService(_type) as WebViewPage;
//var webViewPage = Activator.CreateInstance(_type) as WebViewPage;
if (webViewPage == null)
throw new InvalidOperationException("Invalid view type");
webViewPage.VirtualPath = _virtualPath;
webViewPage.ViewContext = viewContext;
webViewPage.ViewData = viewContext.ViewData;
webViewPage.InitHelpers();
WebPageRenderingBase startPage = null;
if (_runViewStartPages)
startPage = StartPage.GetStartPage(webViewPage, "_ViewStart", _viewStartFileExtensions);
var pageContext = new WebPageContext(viewContext.HttpContext, webViewPage, null);
webViewPage.ExecutePageHierarchy(pageContext, writer, startPage);
}
With the commented out line i completely lost dependency injection within my views so i changed it to the line above which again works fine for the standard views but not for the Layout views. I'd appreciate it if you could show me how the above could be modified to work for the Layout views aswell?
Finally i'm trying to get action filter injection working aswell. I have found two different cases:
Apply the filter to the action via an attribute.
Defining it as a global filter, e.g.:
GlobalFilters.Filters.Add(new TestAttribute());
Neither seem to use the dependency resolver. Therefore i need to do some extra work. Please correct me if there's a better way. To enable the first scenario i did the following:
public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider {
private IUnityContainer _container;
protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
foreach (var attribute in attributes) {
_container.BuildUp(attribute.GetType(), attribute);
}
return attributes;
}
protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
foreach (var attribute in attributes) {
_container.BuildUp(attribute.GetType(), attribute);
}
return attributes;
}
}
And then defined this within my Global.asax file like so:
FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider));
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
This works fine but i was wondering if this is the correct way to do it? To resolve the second case i simply changed where i defined my global filter to the following:
GlobalFilters.Filters.Add(DependencyResolver.Current.GetService<TestAttribute>());
This again now works but is this the correct way to do it?
I'd appreciate the help. Thanks
It's been a while since I originally asked this but I thought I would share what I ended up doing.
In cases where I could not use constructor or attribute injection I solved it by using the DependencyResolver (service locator pattern). For example if I require the service IService I would simply inject it like so:
public IService Service => DependencyResolver.Current.GetService<IService>();
While some may consider this an anti-pattern I have found this performs well, leads to less problems and with new advances in C# I don't think it looks too bad.
However if you are using ASP.NET Core you should never have to use the service locator pattern as it has been rebuilt with dependency injection at the heart of it.

using Moq - void return type method Unit test

I am writing unittest for void method actually that method load the collection in
ViewData["CityList"] method is
public void PopulateCityCombo() {
IEnumerable<Cities> c= service.GetCities();
ViewData["CityList"] = c.Select(e => new Cities{ ID = e.ID, Name = e.Name});
}
now i do not know how to unit test using Moq since controller method is void and not returning data, can any one tell i will achive that.
On a side note, I would shy away from using ViewData within controller methods as per your example. The ViewData dictionary approach is fast and fairly easy to implement, however it can lead to typo's and errors that are not caught at compile time. An alternative would be to use the ViewModel pattern which allows you to use strongly-typed classes for the specific view you need to expose values or content within. Ultimately giving you type safe and compile time checking along with intellisense.
Switching to the ViewModel pattern would allow you to call the PopulateCityCombo() method from your controller to populate a ViewModel that in turn would passed to the corresponding view.
From there you would need to inject a mock service layer into your controllers constructor from your unit test.
// arrange
var mock = new Mock<servicelayer>();
mock.Setup(x=>x.GetCities()).Returns(expectedData);
var controller = new YourController(mock.Object);
// act
var result = controller.ControllerMethod() as ViewResult;
var resultData = (YourViewModel)result.ViewData.Model;
// assert
// Your assertions

Resources