I have a C# Web API and I am trying to get the auto created help documentation to work with IHttpActionResult. I stripped down the example below so its a little easier to read.
For the object, below is a simple example. BusinessObject is just a wrapper. The CollectionBase is CollectionBase : ObservableCollection<T>, ILoadable where T : BusinessObject. Its an older code base that is auto generated but reusing it for this.
public class Value : BusinessObject
{
public int Id { get; set; }
}
public class Values : CollectionBase<Value>
{
public override Value LoadObject(System.Data.IDataRecord record)
{
return new Value();
}
}
For the API side of things. The following works.
public class Values : ApiController
{
public IEnumerable<Value> GetThis()
{
Values values = new Values();
return values;
}
}
The issue comes when I try to do
public IHttpActionResult GetThis()
{
Values values = new Values();
return Ok(values);
}
It doesn't recognize that it should use a different return type. The 'Resource Description' ends up being IHttpActionResult with no sample output. Now I can add
config.SetActualResponseType(typeof(IEnumerable<Value>), "Values", "GetThis");
and it will show a sample output but the 'Resource Description' will still be IHttpActionResult. That is the main issue I am having. I would like to use IHttpActionResult because its very easy to use and can return error codes if needed very easily. I would just like to be able to auto construct the documentation.
UPDATE: Upon some further research, I did fine this post.
Resource Description on Web API Help page is showing "None."
Bascially, you add the response type attribute to the method.
[ResponseType(typeof(IEnumerable<Value>))]
public IHttpActionResult GetThis()
{
Values values = new Values();
return Ok(values);
}
Although this technically works and I have modified my existing code to use this. It would still be nice if there was a way to have it automatically figure it out somehow. Not sure if this is possible or not.
This works for what I am doing. Its a little tedious to have to include every time but it allows me to return error codes if necessary and retain the help documentation functionality.
[ResponseType(typeof(IEnumerable<Value>))]
public IHttpActionResult GetThis()
{
Values values = new Values();
return Ok(values);
}
Resource Description on Web API Help page is showing "None."
Related
I have a typical API with some CRUD operations. I typically need to get certain objects, based on different parameters.
One way to do it would be to have methods like:
GetProjectsByCustomerId(int customerId);
GetProjectsBySigneeId(int signeeId);
However, in my service layer (ProjectService in this case) I usually use a method such as the following where ProjectSpecification typically has quite a lot of fields and even lists:
public IEnumerable<Project> GetBySpecification(ProjectSpecification projectSpecification)
That means, in my dream world I would like to have endpoints such as:
/api/projects (empty specification, return full list)
/api/projects?customerid=2 (gets projects for customer with id 2)
/api/projects?signeeid=2,3 (get projects with signee id 2 and 3)
My question is - how is this done
My first attempt was adding this in my ProjectController (calling my ProjectService):
public class ProjectsController : ApiController
{
public IEnumerable<Project> GetProjects(ProjectSpecification projectSpecification)
{
var projects = _projectService.GetBySpecification(projectSpecification);
return projects;
}
}
But lets say I open this URL:
/api/Projects?CustomerId=2
This is not parsed into a ProjectSpecification viewmodel. However, if I change my controller signature to:
public IEnumerable<Project> GetProjects(int customerid) { }
It would work, because it's a simple type.
I could of course build some parameter-hell, but I guess there is something super obvious MVC magic I am missing - probably in the routing? :-)
Referencing documentation
Parameter Binding in ASP.NET Web API : [FromUri]
To force Web API to read a complex type from the URI, add the
[FromUri] attribute to the parameter.
For example assuming
public class ProjectSpecification {
public int CustomerId { get; set; }
//...other properties
}
public class ProjectsController : ApiController {
[HttpGet]
public IHttpActinoResult GetProjects([FromUri]ProjectSpecification projectSpecification) {
return Ok(projectSpecification);
}
}
The client can put the CustomerId value in the query string.
For example:
/api/Projects?CustomerId=2
and Web API will use them to construct a ProjectSpecification with the CustomerId set to 2 .
I'm in the process of designing a RESTful Web API and have bumped into the following problem: I need a controller to retrieve collections (called Sections) of a hierarchical structure as well as to retrieve a single part (a single Section). If I need a collection I have to refer to the ID of the root Section which gives me a subtree of the whole structure. So I went ahead and defined a SectionsController like this:
public class SectionsController : ApiController
{
// GET api/sections/5
// Gets a subtree.
public IEnumerable<Section> Get(int rootId)
{
...
}
// GET api/sections/5
// Gets a single section.
public Section Get(int sectionId)
{
...
}
Which obviously doesn't work as the signatures are identical. What is the recommended way to go about this?
If you want to follow standard REST patterns you should introduce a slightly different API:
public class SectionsController : ApiController
{
// GET api/section
public IEnumerable<Section> GetAll()
{
...
}
// GET api/section/5
public Section Get(int sectionId)
{
...
}
Normally you should use singular resources and provide identifier only for a specific one. You can't have same URLs, even with different controllers.
Reading this post on SO regarding image transfer and following the link provided I realized there is a very simple solution to this problem that respects REST and at the same time doesn't require additional controllers.
Just return a collection of the subtree IDs within the object requested for a particular ID, i.e.
public class Section
{
public int Id { get; set; }
public string Name { get; set; }
public int[] DescendantIds { get; set; }
}
So with a single call to
api/section/5
I get all the details for the section with ID 5 as well as the IDs of the sections below. Yes, there's some overhead involved, so you have to decide for yourself if this solution is for you.
I'm trying to setup Facebook Notification API.
I have an APi Controller with RealtimeUpdate() - Get, will be used just for verification of endpoint.
As is written in Fb Docs:
Firstly, Facebook servers will make a single HTTP GET to your callback
URL when you try to add or modify a subscription. A query string will
be appended to your callback URL with the following parameters:
hub.mode - The string "subscribe" is passed in this parameter
hub.challenge - A random string
hub.verify_token - The verify_token value you specified when you created the subscription
From here I have a problem - I have no idea how to handle this dots in query params names. I google a lot, and did not find the solution.
Can somebody please say to me how to get data from this hub.* values?
Thank you!
Update your method signature using the FromUri attributes, like this:
public string Get(
[FromUri(Name="hub.mode")]string mode,
[FromUri(Name="hub.challenge")]string challenge,
[FromUri(Name="hub.verify_token")]string verifyToken
)
{
/* method body */
}
The parameters will be bound from the query string using the specified names.
Slightly different form Steve's answer.
In case you need to have a normal controller instead of an Api one (if you are inheriting from Controller rather tha ApiController), the follow worked for me:
namespace Name
{
public class Hub
{
public string Mode { get; set; }
public string Challenge { get; set; }
// ReSharper disable once InconsistentNaming
public string Verify_Token { get; set; }
}
public class FacebookWebHooksController : Controller
{
[System.Web.Http.HttpGet, ActionName("Callback")]
[AllowAnonymous]
public ContentResult CallbackGet(Hub hub)
{
if (hub.Mode == "subscribe" && hub.Verify_Token == "YOUR_TOKEN")
return Content(hub.Challenge, "text/plain", Encoding.UTF8);
return Content(string.Empty, "text/plain", Encoding.UTF8);
}
}
[HttpPost]
[AllowAnonymous]
public ActionResult Callback()
{
Request.InputStream.Seek(0, SeekOrigin.Begin);
var jsonData = new StreamReader(Request.InputStream).ReadToEnd();
}
}
The Model Binder has some illegal characters, of which I believe '.' is a special character, used primarily to bind complex objects. When all else fails, you can look at Request.QueryString and Request.Form directly, just like in ASP.NET WebForms.
You can also try using a complex object that has a Property named hub with subproperties mode, challenge, and verify_token. This might just do the trick.
Even many Q/A on the subject, I didn't find a clear answer for this question:
What's the best design practice for adding business rules (i.e, validations) to entity classes.
I simply want to check some validations before setting the underlying entity value:
public Property
{
get { return base.Property; }
set
{
// Do some validations or other business logic
base.Property = value;
}
}
It doesn't make sense to create a new class from scratch in BLL when all properties are already there in entity class. On the other hand, entity classes need to be extended with business logic rules.
Using interface need extra work, because a change in DAL (entity) would be reflected in both interface and BLL class.
I'm not sure if inheriting from entity class and overriding it's properties and adding extra properties and methods is a good idea or not.
A sample pseudo code in more helpful to me.
Thanks
I would like to elaborate on Stephen Cleary's answer. He is correct in using the partial class/methods to handle business rules in EF. However, he did not go into much detail about what to do within that partial class/method. I created a URL shortening service on my blog to use as an example for this. My ShortURL entity has only two columns/properties. Url and ID.
I wanted to validate that the URL being shortened is a valid URL before it actually stores it in the database through EF. So I created a partial class and method like so:
public partial class ShortURL
{
partial void OnUrlChanging(string url)
{
if (!Regex.IsMatch(url, #"(^((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?)"))
throw new Exception("Not a valid URL.");
}
}
This stopped EF from changing the property, leaving it NULL. But that's all it did. It didn't give me an easy way to get at the error message and display it to the user (that I am aware of EDIT: According to http://www.sellsbrothers.com/posts/Details/12700 IDataErrorInfo is the only way to get the error message to display properly in ASP.NET MVC) so I followed another example I found in the dark recesses of the web somewhere and I made my partial class inherit from IDataErrorInfo. I then implemented the interface and included a private dictionary object to store error messages in.
public partial class ShortURL : IDataErrorInfo
{
private Dictionary<string, string> errors = new Dictionary<string, string>();
partial void OnUrlChanging(string url)
{
if (!Regex.IsMatch(url, #"(^((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?)"))
errors.Add("Url", "Not a valid URL.");
}
public string Error
{
get { return string.Empty; } //I never use this so I just return empty.
}
public string this[string columnName]
{
get
{
if (errors.ContainsKey(columnName))
return errors[columnName];
return string.Empty; //Return empty if no error in dictionary.
}
}
}
Now, I have a fully-functioning way to store, retrieve, and display error messages. Now back in my controller (in MVC) I am able to do if (!ModelState.IsValid)
[HttpPost]
public ViewResult URLShortener(ShortURL shortURL)
{
if (!ModelState.IsValid)
return View();
shortURL.Url = shortURL.Url.ToLower().StartsWith("www.") ? "http://" + shortURL.Url : shortURL.Url;
shortURLRepository.AddShortURL(shortURL);
object model = "http://www.u413.com/" + ShortCodes.LongToShortCode(shortURL.UrlID);
//Not related to this answer but I had to cast my string as a generic object because the View() method has a (string, string) constructor that does something totally different. My view actually uses string as the model. I know I know, I could have just used ViewBag.
return View("ShowUrl", model);
}
There ya go. A working example of how to not only extend EF's partial methods, but also how to propagate the validation back to the UI. Let me know if anything needs improving or if there was something I missed.
Check out your EF designer-generated code.
Each property Property is actually implemented like this:
public global::System.String Property
{
get
{
return _Property;
}
set
{
OnPropertyChanging(value);
ReportPropertyChanging("Property");
_Property = StructuralObject.SetValidValue(value, false);
ReportPropertyChanged("Property");
OnPropertyChanged();
}
}
private global::System.String _Property;
partial void OnPropertyChanging(global::System.String value);
partial void OnPropertyChanged();
The partial method On-Property-Changing is where you can do single-property validation or business logic.
Xaqron, the best way I have found it to use Partial Classes, for example, if you have a class in your EF called PropertyListing you can use a partial class like this:
Partial Public Class PropertyListing
Inherits EntityObject
'Do something here
End Class
You can now extend the class as little or as much as you want without much fuss. The example is in VB but you get the jist of it
I need advice on how to return a limited set of data from an MVC controller.
Lets say I have a class that is constructed like so:
public interface ICustomerExpose
{
string Name {get; set;}
string State {get; set;}
}
public interface ICustomer: ICustomerExpose
{
int Id {get; set;}
string SSN {get; set;}
}
public class Customer: ICustomer
{
...
}
In my MVC project I have a controller action that returns customer data. The project is actually more like a web service as there is no View associated with the data... we use the XmlResult (provided by the MVCContrib project). The controller action looks like this:
// GET: /Customer/Show/5
public ActionResult Show(int id)
{
Customer customer = Customer.Load(id);
... // some validation work
return new XmlResult((ICustomerExpose)customer);
}
The above controller code does not work like I want it to. What I want to happen is that only the Name and State properties are serialized and returned in the XmlResult. In practice the whole customer object is serialized including the data I definitely don't want exposed.
I know the reason this doesn't work: you can't serialize an interface.
One idea floated around the office was to simply mark the properties Name and State as [XmlIgnore]. However, this doesn't seem like a good solution to me. There might be other instances where I want to serialize those properties and marking the properties on the class this way prohibits me.
What is the best way to achieve my goal of only serializing the properties in the ICustomerExpose interface?
Addendum:
For those interested in what XmlResult does here are the relevant parts of it:
public class XmlResult : ActionResult
{
private object _objectToSerialize;
public XmlResult(object objectToSerialize)
{
_objectToSerialize = objectToSerialize;
}
/// <summary>
/// Serialises the object that was passed into the constructor
/// to XML and writes the corresponding XML to the result stream.
/// </summary>
public override void ExecuteResult(ControllerContext context)
{
if (_objectToSerialize != null)
{
var xs = new XmlSerializer(_objectToSerialize.GetType());
context.HttpContext.Response.ContentType = "text/xml";
xs.Serialize(context.HttpContext.Response.Output, _objectToSerialize);
}
}
}
You can try this, however I am not sure if it works with xml serializers:
return new XmlResult(new { customer.Name, customer.State });
See this related question which recommends using an anonymous type.
// GET: /Customer/Show/5
public ActionResult Show(int id)
{
Customer customer = Customer.Load(id);
... // some validation work
var result = from c in cusomter
select new
{
Name = c.Name,
State = c.State,
};
// or just
var result = new
{
Name = customer.Name,
State = customer.State,
};
return new XmlResult(result);
}
Consider using, just for this one problem, XML literals in VB9 rather than serialization. Seriously. Just give it 20 minutes of your time. There's many options.
http://www.hanselman.com/blog/TheWeeklySourceCode30VBNETWithXMLLiteralsAsAViewEngineForASPNETMVC.aspx
http://www.hanselman.com/blog/XLINQToXMLSupportInVB9.aspx
http://blogs.msdn.com/dmitryr/archive/2008/12/29/asp-net-mvc-view-engine-using-vb-net-xml-literals.aspx
http://haacked.com/archive/2008/12/29/interesting-use-of-xml-literals-as-a-view-engine.aspx
http://www.infoq.com/news/2009/02/MVC-VB
For what you're doing, returning XML as a poor-man's Web Service, this is tailor-made.
I ended up just doing the XmlIgnore as co-workers suggested, even though this left me with some undesirable (or so I thought) behaviors.
To get around the fact that XmlIgnore would continue hiding properties that I might want serialized later I asked another question trying to find a way to around that issue. Cheeso came up with a great answer making the XmlIgnore the best route (in my opinion) to take.