ServiceStack self host windows service question, at the link there are two Services: TodoService.cs and HelloService.cs.
I am a little confused, are they different examples or related each other?
//Register REST Paths
[Route("/todos")]
[Route("/todos/{Id}")]
public class Todo //REST Resource DTO
{
public long Id { get; set; }
public string Content { get; set; }
public int Order { get; set; }
public bool Done { get; set; }
}
//Todo REST Service implementation
public class TodoService : RestServiceBase<Todo>
{
public TodoRepository Repository { get; set; } //Injected by IOC
public override object OnGet(Todo request)
{
if (request.Id == default(long))
return Repository.GetAll();
return Repository.GetById(request.Id);
}
//Called for new and update
public override object OnPost(Todo todo)
{
return Repository.Store(todo);
}
public override object OnDelete(Todo request)
{
Repository.DeleteById(request.Id);
return null;
}
}
And
/// <summary>
/// Define your ServiceStack web service request (i.e. the Request DTO).
/// </summary>
[Description("ServiceStack's Hello World web service.")]
[Route("/hello")]
[Route("/hello/{Name*}")]
public class Hello
{
public string Name { get; set; }
}
/// <summary>
/// Define your ServiceStack web service response (i.e. Response DTO).
/// </summary>
public class HelloResponse : IHasResponseStatus
{
public string Result { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
/// <summary>
/// Create your ServiceStack web service implementation.
/// </summary>
public class HelloService : ServiceBase<Hello>
{
protected override object Run(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
They are separate examples of different services you can build with ServiceStack. The ServiceStack examples are made available in a single solution called ServiceStack.Examples, but it contains separate projects.
You are looking in a directory called StarterTemplates.Common, this is simply shared by several of the examples for code reusability. The folder structure does not indicate that TodoService.cs and HelloService.cs are directly related.
The individual projects of the ServiceStack Examples, can be seen here.
Backbone.js TODO app with REST and Redis backend
Creating a Hello World Web service from scratch
Related
When I add a type to AutoQuery, with:
[Route("/templates")]
public class SearchTemplates : QueryDb<Template>
{
public int? Id { get; set; }
public string Name { get; set; }
}
then I can query this object by Id or Name (or whatever other attributes I would add, that the POCO Template has). However it always returns list of items.
It's very useful to be able to GET a single item (not a search result).
This is how I do it:
[Route("/template/{Id}","GET")]
public class SingleTemplate : IReturn<Template>
{
public int Id { get; set; }
}
public Template Get(SingleTemplate request)
{
return Db.LoadSingleById<Template>(request.Id);
}
With all the new AutoQuery and AutoCRUD, it seems to me that the "return a single item by its URL" could also be automatic?
No, All AutoQuery QueryDb<T> services return the same fixed QueryResponse Response DTO as per its Service Contract, i.e:
public abstract class QueryDb<T>
: QueryBase, IQueryDb<T>, IReturn<QueryResponse<T>> { }
public abstract class QueryDb<From, Into>
: QueryBase, IQueryDb<From, Into>, IReturn<QueryResponse<Into>> { }
public class QueryResponse<T> : IQueryResponse
{
public virtual int Offset { get; set; }
public virtual int Total { get; set; }
public virtual List<T> Results { get; set; }
public virtual Dictionary<string, string> Meta { get; set; }
public virtual ResponseStatus ResponseStatus { get; set; }
}
A single result would still populate the Results property, so the JSON wire format would look like:
{ "results":[ {/*Template*/} ] }
You could create your own Custom AutoQuery Implementation that utilizes AutoQuery's IAutoQueryDb API to return your own custom populated DTO but then your Request DTO should NOT inherit from QueryDb<T> as not returning a QueryResponse<T> would break the explicit Service contract of the Request DTO (and all clients expecting it), i.e. you would instead just create a normal ServiceStack Service returning your own custom Response Type.
I am using .net core for expose API. When I call api from postman, some method not hitting, get 404 not found error message.
[HttpPost]
public async Task<bool> AddLogs([FromBody]List<LogModel> model)
{
var result = false;
foreach (var item in model)
{
result = await _logService.Insert("Logs", item);
}
return result;
}
public class LogModel: TableEntity
{
public int Status { get; set; }
public bool IsBreak { get; set; }
public string Location { get; set; }
public DateTime StartDateAndTime { get; set; }
public DateTime EndDateAndTime { get; set; }
public string Remarks { get; set; }
public int Id { get; set; }
}
When I call the api 'AddLogs' , get not found error message.
But when try ,
[HttpPost]
public async Task<bool> Post()
{
return true;
}
It will return the true value.
But I noted that when I call in localhost 'AddLogs' api working fine. It will hit the api. But When I publish in azure, it shows me not found.
I test in my site and it works well.
The reason for this is that the deployment or default ASP.NET Core Web API template does not include a default document in the root directory of the web site. For example, index.htm, defualt.aspx, default.htm are default documents and IIS will deliver them if there is no specific file provided when accessing the URL.
You could set [HttpPost("AddLogs/")] to specify the AddLogs action if you have several httppost method. Remember also add the following code in Configure method.
app.UseMvc(routes =>
{
routes.MapRoute(name: "default", template: "api/{controller}/{action}/{id?}");
});
I have created a customer service using ServiceStack but i am not able to pass a list of object from this method.
Customer Service -
public class EntityService : Service
{
/// <summary>
/// Request for entity information list
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public object Any(List<CustomerRequest> request)
{
}
}
Request DTO -
[Route("/api/V1/GetCustomerDetails", Verbs = "POST", Notes = "")]
public class CustomerRequest : IReturn<List<CustomerResponse>>
{
[ApiMember(Name = "GetCustomerDetails", Description = "GetCustomerDetails", ParameterType = "body", DataType = "List<BaseRequest>", IsRequired = true)]
List<BaseRequest> _baseRequest {get;set;}
}
public class BaseRequest
{
public string CustId { get; set; }
public string CustName { get; set; }
public string CustAddress { get; set; }
}
Could you please let me know what is the correct way to pass list of object in ServiceStack Post operation.
Each Service in ServiceStack needs to accept a single named concrete Request DTO Type. You can look at the AutoBatched Requests for how to send multiple requests.
E.g, if you want to a Service to accept a List of Types you can inherit List<T>, e.g:
public class CustomerRequests : List<CustomerRequest>{}
public class EntityService : Service
{
public object Any(CustomerRequests request)
{
}
}
public class PageRoleService
{
public void SetRoles(Page page, User activeUser)
{
var rb = page.Project.ProjectType.GetRoleFor(activeUser.UserType);
page.RolesForPage.Add(activeUser, rb);
var managers = GetAllManagersOf(activeUser);
foreach (var m in managers)
{
page.RolesForPage.Add(m, rb);
}
}
}
public class Project : Entity
{
public ProjectType ProjectType { get; set; }
public IList<Page> Pages { get; set; }
}
public class Page : Entity
{
public string Name { get; set; }
public Project Project { get; set; }
public IDictionary<User, RoleBehaviour> RolesForPage { get; set; }
}
public class ProjectType : Entity
{
public IQueryProcessor QueryProcessor { get; set; }
public IList<RoleBehaviour> RoleBehaviours { get; set; }
public RoleBehaviour GetRoleFor(USerType userType)
{
var behaviour = return QueryProcessor.Execute(new GetRolesByUserAndProjectTypeQuery() {
ProjectType = this,
UserType = userType
});
// Filter behaviour attributes for project type properties, business rules, etc...
// FilterBehaviour(behaviour);
return behaviour;
}
}
public class GetRolesByUserAndProjectTypeQuery
{
public UserType UserType { get; set; }
public ProjectType ProjectType { get; set; }
}
public class GetRolesByUserAndProjectTypeQueryHandler
{
public Db Db { get; set; }
public RoleBehaviour Execute(GetRolesByUserAndProjectTypeQuery query)
{
return Db.FirstOrDefault(r => r.UserType == query.UserType && r.ProjectType == query.projectType);
}
}
public class RoleBehaviour : Entity
{
public Role ROleForArea1 { get; set; }
public Role ROleForArea2 { get; set; }
public UserType UserType { get; set; }
public ProjectType ProjectType { get; set; }
public IDictionary<string, string> Attributes { get; set; }
}
public enum UserType
{
A,
B,
C,
D
}
public class Role : Entity
{
public IList<string> Permissions { get; set; }
}
I don't use repository, no need data abstraction, I use CQRS for crud operations. (CreateProjectCommand, GetRolesByUserAndProjectTypeQuery, etc..)
Users related a lot of project and page. Users have more than role for each Page Entity and is dynamically created when user (client) request to fetch All projects page or single page item.
My Page Role Service determinates page roles for active user and its managers. My MVC Controller use PageRoleService.
PageRoleService is Application Service or Domain Service or .....?
QueryProcessor in Entity (ProjectType) is invalid approach? How can handle this/their problems without lazy or eager loading?
RoleBehaviour is Entity or Value Object?
PageRoleService is a service or business logic in domain?
I know that I'm some years later, but:
I would put away the base class Entity, because it looks that this are just Dtos returned by the queryhandler (infact GetRolesByUserAndProjectTypeQueryHandler.Execute returns a RoleBehaviour).
Given this, I think that:
PageRoleService is a simple service that completes a Dto, hence it looks a kind of factory
Given that ProjectType here has two different roles (a Dto and Entity, and this is against CQRS), if:
it's a Dto, then use a service/factory/ORM to load extra data on it
it's an Entity, try to load all the data that's needed by it. This because there're great changes that you'll need it on the way to execute your command (great explanation about DDD and entities).
The object has it's own identity? Has it an Id that, even if things will change, remains the same? Looking at it, it looks just a Dto, with nothing really interesting (at business level).
see 1.
My issue:
A custom validation attribute is called twice and not once when calling a webapi post method (with EF) - I am not sure if this is normal and would like a definitive answer. It validates at the following points:
Just before the breakpoint enters the webapi application post method (presumably populating ModelState)
Again just before the insert takes place (db.Applications.Add(application))
[Table("Applications")]
public class Application
{
/// <summary>
/// ApplicationID (auto-increment)
/// </summary>
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ApplicationID { get; set; }
/// <summary>
/// Name of the application
/// </summary>
[Required]
[MaxLength(255)]
public string ApplicationName { get; set; }
/// <summary>
/// Application ref (for friendly lookups)
/// </summary>
[Required]
[MaxLength(150)]
[UniqueApplicationReference] // <<<<<<< My custom validation attribute
public string ApplicationRef { get; set; }
/// <summary>
/// Application status
/// </summary>
[Required]
public bool? ApplicationStatus { get; set; }
public virtual ICollection<ApplicationFeature> ApplicationFeatures { get; set; }
}
Here is my webAPI end point:
public HttpResponseMessage PostApplication(Application application)
{
if (ModelState.IsValid)
{
db.Applications.Add(application);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, application);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = application.ApplicationID }));
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
Is the better solution simply to provide a Data Transfer class for application object with little/simple validation on it for the purposes of passing the data and then let any domain specific validation errors just bubble back via HttpResponseMessage therefore lookups are only run when the insert is attempted with reasonable data?
Thank you!
Dan.