Introducing ServiceStack

Posted by: Ravi Kiran , on 11/19/2014, in Category ASP.NET
Views: 62924
Abstract: ServiceStack is a configuration free, code-first, light-weight framework built on top of ASP.NET for building services and web applications. This article will get you started with ServiceStack and also get your hands dirty with it.

When we think of building web applications or services in .NET, we usually confine ourselves to core ASP.NET technologies. There is no doubt that Microsoft has put in a lot of efforts in building some awesome web frameworks and tools to make our lives easier, but there are alternatives to Microsoft's set of technologies that are worth taking a look at. ServiceStack is one such option.

ServiceStack is a thoughtfully architected, obscenely fast, thoroughly enjoyable web services for all.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free .NET tutorials from experts

ServiceStack is a configuration free, code-first, light-weight framework built on top of ASP.NET for building services and web applications. As the name suggests, it is a stack of services. It provides with just everything that one needs for building end-to-end web services. In a way, we can say that it is a light-weight alternative to WCF, Web API, ASP.NET MVC, ASP.NET Web Forms and any framework using which we can develop web apps or APIs.

What is the ‘Stack’ in ServiceStack?

ServiceStack has a big list of features stacked in that is just enough to build any kind of service. The following are key components in the stack:

1. REST, SOAP and Message Queuing Services

2. Automatic Serialization/Deserialization to/from a variety of data formats including JSON, XML and CSV (JSON parser is the fastest parser in .NET)

3. A light weight ORM package called OrmLite

4. Dependency Injection

5. Razor views

6. Logging

7. Bundling

8. Security

To learn more about the features, you can visit https://servicestack.net/features. The good thing is, ServiceStack doesn’t depend on any third party to support any of its feature. It is a self-contained and self-independent framework.

Why ServiceStack?

Using ServiceStack, one can quickly build APIs that can be hosted anywhere (IIS, Windows Service, Self-host or Mono) and consumed from anywhere. Building a ServiceStack API is really easy as it doesn’t need a lot of configurations before getting the service up and running. ServiceStack defines a set of conventions that make the job of writing and exposing services easy.

The pieces in the ServiceStack are totally independent of each other and can be used in isolation. For example, if you only want the JSON parser of ServiceStack for your application, you can include it alone and use it.

In addition to all the rich features, ServiceStack embraces the practices of clean code, which means, the logic that we write to expose services using ServiceStack are fully testable.

As listed in the features, ServiceStack supports Razor views. This feature enables to create Razor pages to render the data exposed by the Services.

Student Report Application

In this article, we will build a Student Report application using ServiceStack. By the end of this article, you will be familiar with the following features of ServiceStack:

1. REST Services

2. OrmLite

3. Dependency Injection

4. Razor Views

Setting up the project

Open Visual Studio 2013 and choose File > New > Project, create an empty ASP.NET web application and name it StudentReports. Install the following NuGet packages in this project:

1. Bootstrap

2. ServiceStack

3. ServiceStack.OrmLite.SqlServer

4. ServiceStack.Razor

To bootstrap ServiceStack, we need to register the ServiceStack components when the application starts. To do this, add a new class to the project and name it AppHost. This class should inherit from ServiceStack.AppHostBase class.

The class AppHostBase doesn’t have a non-parameterized constructor. The constructor expects a name for the service and a list of assemblies where the services are defined. As we haven’t created services yet, add a class named StudentService to the project. This class can be left empty for now. We will come back to this class later to add code to it.

The AppHostBase class has an abstract method, Configure which will be overridden in our AppHost class. This method is used to configure the components in ServiceStack. We can leave it empty for now. Following is the code in AppHost as of now:

public class AppHost : AppHostBase
{
    public AppHost() : base("Student report Service", typeof(StudentService).Assembly) { }

    public override void Configure(Funq.Container container)
    {
        
    }
}

And finally to finish the setup, we need to invoke Init() method of the AppHost in Application_Start event of Global.asax. If the project doesn’t have a Global.asax file yet, add it and modify the Application_Start event:

protected void Application_Start(object sender, EventArgs e)
{
    (new AppHost()).Init();
}

Note: If you want to avoid the above steps while creating a ServiceStack project, install the ServiceStackVS extension through extensions gallery. It installs some project templates that include all the required hooks to build a ServiceStack application.

vs-extension

Writing basic services using ServiceStack

ServiceStack is based on DTOs (Data Transfer Object model). To define a service, we need at least one request DTO class. For instance, say we need the ID of a student in the service, then the request DTO can be a class with the field ID. If you need data, additional properties can be added to the DTO class.

We need to expose any service through an endpoint. Endpoints can be created using Route attribute defined on ServiceStack namespace. Unlike ASP.NET Web API, where we define routes in the service controller, ServiceStack routes are defined on DTOs.

Following is the DTO for student data:

[Route("/students")]
[Route("/students/{Id}")]
public class StudentRequestDto
{
    public int Id { get; set; }
}

As you see, the above DTO exposes two endpoints: one plain endpoint with no parameters and the second one with Id as the parameter.

You can optionally define response DTO as well. Response DTO can be specified as return type on the request DTO as follows:

public class StudentRequestDto : IReturn

Now let’s define a service method to respond to the requests. A service class should be a child to ServiceStack.Service class. Open the StudentService class created earlier and add the following code to it:

public class StudentService : Service
{
    public object Any(StudentRequestDto dto)
    {
        if (dto.Id != default(int))
        {
            return new { Id = dto.Id, Name = "Ravi" };
        }
        else
        {
            return new ArrayList { 
                new { Id = 1, Name = "Ravi" },
                new { Id = 2, Name = "Kiran" }
            };
        }
    }
}

Names of the methods defined in the service classes have to follow conventions to get some magic applied on them. Here, the method Any would respond to any kind of request sent to the endpoints defined over StudentRequestDto. Now if you run the application, the following page would appear in the browser:

service-default-page

The service by default supports all the formats listed on the page and as we can see, it can be consumed as a SOAP as well as a REST service. The links in the page provide help information about consuming the API. Change the URL to:

http://localhost:/students?format=json

It would display the data in the form of JSON in the browser:

json-data

You may not like the Pascal Case notation in JSON data. You can modify format of the cases in Configure method of the AppHost class. Add the following statement to convert JSON data into camel case:

ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

Similarly, change value of format to any of the supported types and you will see the corresponding result.

To restrict a route to HTTP methods, we can specify the list of methods in the Route attribute. Following routes demonstrate 2 cases of restricting:

[Route("/students", Verbs = "GET, POST")]  //Only GET and POST requests are allowed on this route
[Route("/students/{id}", Verbs = "GET")]  //Only GET request is allowed on this route
public class StudentRequestDto
{}

In the service class, we need to define the corresponding methods following their conventions.

 public class StudentService : Service
 {
     public object Get(StudentRequestDto dto)
     {
    //Implementation
     }

     public object Post(StudentRequestDto dto)
     {
    //Implementation
     }
 }

For the demo Student Reports application, we don’t need the POST event on Student. But we will be performing GET, POST and PUT operations on Marks. Following is the Marks DTO with required Routes:

[Route("/marks/student/{StudentId}", Verbs = "GET")]
[Route("/marks/{MarksId}", Verbs = "GET, PUT")]
[Route("/marks",Verbs="POST")]
public class MarksRequestDto
{
    public int MarksId { get; set; }
    public int StudentId { get; set; }
    public int MarksAwarded { get; set; }
    public int MaxMarks { get; set; }
    public string Subject { get; set; }
}

Notice the first route in the above snippet. This route is to enable fetching marks of a particular student. The route is defined this way to avoid confusion between accepting MarksId and StudentId into the API. We will define a service for this DTO later.

Using OrmLite and Dependency Injection

ServiceStack includes a light-weight micro ORM called OrmLite. It is one of the fastest .NET ORMs. It is not as configurable as Entity Framework, but still provides a good set of features to interact with databases. OrmLite has DB specific implementations for all major databases including SQL Server, Oracle and MySql and some others like PostgreSQL, FirebirdSql and Sqlite. We will be using the SQL Server version.

As a first step, create a new database on SQL Server and name it StudentDb. Add the following connection string to the Web.config:


To work with the database, we need an object of IDbConnectionFactory type. OrmLiteConnectionFactory is an implementation of this interface. Following statement creates an object of this class:

var ormLiteConnectionFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["studentDbConn"].ConnectionString,  
ServiceStack.OrmLite.SqlServer.SqlServerOrmLiteDialectProvider.Instance);

Let’s make this object available to the entire application through the built-in IoC container of ServiceStack Funq. Funq in ServiceStack is based on an open-source IoC container named Funq (http://funq.codeplex.com/) with the framework adding more capabilities to its implementation. ServiceStack internally uses Funq to register objects of the Service classes, Filters and Validators.

Let’s register the above object to the container of Funq. Configure method of the AppHost class already has a reference to Funq’s container. Following statement registers the dependency:

container.Register(ormLiteConnectionFactory);

Objects registered to Funq are injected through both constructor and property injection.

To read more about Funq, visit ServiceStack’s wiki on GitHub (http://bit.ly/dncm15-sswiki).

Let’s set up the database with two tables to store Student data and marks and fill-in some data into the tables. Following are the classes for Student and Marks tables:

public class Student
{
    [AutoIncrement]
    public int StudentId { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
    public int CurrentClass { get; set; }
}

public class Marks
{
    [AutoIncrement]
    public int Id { get; set; }

    public int MarksAwarded { get; set; }
    public int MaxMarks { get; set; }
    public string Subject { get; set; }

    [References(typeof(Student))]
    public int StudentId { get; set; }
}


The AutoIncrement attribute in above snippets denotes a table column with auto incrementing values, which is Identity column in case of SQL Server. References attribute in the Marks class defines a foreign key reference.

To fill these tables with data, let’s create a new class DbInitializer. This class will have just one static method InitializeDb. This method checks for existence of tables, creates the tables and fills in data if the tables don’t exist yet.

public class DbInitializer
{
    public static void InitializeDb(IDbConnectionFactory dbConnectionFactory)
    {
        var students = new List()
        {
            new Student(){Name="Andrew",City="Boston",CurrentClass=2},
            new Student(){Name="Richa",City="Chicago",CurrentClass=3},
            new Student(){Name="Dave",City="Phoenix",CurrentClass=4},
            new Student(){Name="Ema",City="Washington",CurrentClass=5},
            new Student(){Name="Filip",City="Texas",CurrentClass=6},
            new Student(){Name="Maggi",City="Los Angeles",CurrentClass=7},
            new Student(){Name="Nathan",City="Atlanta",CurrentClass=8}
        };

        var studentMarks = new List()
        {
            new Marks(){Subject="Mathematics",MarksAwarded=80,MaxMarks=100, StudentId=1},
            new Marks(){Subject="English",MarksAwarded=70,MaxMarks=100, StudentId=1},
            new Marks(){Subject="Hindi",MarksAwarded=75,MaxMarks=100, StudentId=1},
            new Marks(){Subject="Mathematics",MarksAwarded=60,MaxMarks=100, StudentId=2},
            new Marks(){Subject="English",MarksAwarded=90,MaxMarks=100, StudentId=3},
            new Marks(){Subject="Hindi",MarksAwarded=85,MaxMarks=100, StudentId=2},
            new Marks(){Subject="Mathematics",MarksAwarded=90,MaxMarks=100, StudentId=2},
            new Marks(){Subject="English",MarksAwarded=80,MaxMarks=100, StudentId=3},
            new Marks(){Subject="Hindi",MarksAwarded=80,MaxMarks=100, StudentId=3}
        };

        using (var db = dbConnectionFactory.OpenDbConnection())
        {

            if (!db.TableExists("Student"))
            {
                db.CreateTable();
                db.InsertAll(students);
            }

            if (!db.TableExists("Marks"))
            {
                db.CreateTable();
                db.InsertAll(studentMarks);
            }

        }
    }
}

To operate with these tables, we need repositories. As we have just two tables and we need limited number of operations to be performed on the tables, one repository class will suffice. The repository class would be performing the following operations:

  • Get all students
  • Get student details by id
  • Get marks of a student
  • Get marks by marks ID
  • Add marks of a student
  • Update marks of a student

We need a connection factory object to establish a connection to the database. As the object is already added to Funq, we will get it through property injection. Following is the repository class with a method that fetches all students from the DB:

public class StudentDbRepository
{
 public IDbConnectionFactory DbConnectionFactory { get; set; }

 public List GetStudents()
 {
     using (var db = DbConnectionFactory.OpenDbConnection())
     {
         return db.Select();
     }
 }
}

In the above snippet, Select() is a generic method that gets data from the table represented by the class specified with it. We enclosed the data operation inside a using block to dispose the connection object immediately after the operation is done. To apply filter while fetching data, we can pass a lambda expression to the Select() method as shown in the following methods:

public List GetMarksByStudent(int studentId)
{
    using (var db = DbConnectionFactory.OpenDbConnection())
    {
        return db.Select(m => m.StudentId == studentId);
    }
}

public Marks GetMarks(int marksId)
{
    using (var db = DbConnectionFactory.OpenDbConnection())
    {
        return db.Select(m => m.Id == marksId).FirstOrDefault();
    }
}

To add marks of a student, we can call the Insert() method on the connection object. If the Insert() method adds data to a table with an identity column in it, the identity value can be fetched using LastInsertedId() method on the same connection object. Following snippet demonstrates this while adding a new entry of marks:

public int AddMarks(Marks marks)
{
    using (var db = DbConnectionFactory.OpenDbConnection())
    {
        db.Insert(marks);
        return (int)db.LastInsertId();
    }
}

The last operation that we need to perform is updating marks. It is a straight forward operation and returns the number of rows affected.

public int UpdateMarks(Marks marks)
{
    using (var db = DbConnectionFactory.OpenDbConnection())
    {
        return db.Update(marks);
    }
}

With this, the repository is completed and now we can use it in our services. As the service classes need an instance of the repository class, let’s make the instance available through the dependency injector Funq.

container.Register(c => new StudentDbRepository()).ReusedWithin(ReuseScope.Request);

The ReuseWithin() method chained with the Register() method is used to define scope of an instance registered. The repository object is scoped within the HTTP request. The object is destroyed as soon as the request ends.

Following are the modified StudentService and MarksService classes.

public class StudentService : Service
{
    StudentDbRepository repository;

    public StudentService(StudentDbRepository _repository)
    {
        repository = _repository;
    }

    public object Get(StudentRequestDto studentDto)
    {
        if (studentDto.Id == default(int))
        {
            return repository.GetStudents();
        }
        else
        {
            return repository.GetStudentById(studentDto.Id);
        }
    }
}    

public class MarksService : Service
{
    StudentDbRepository repository;

    public MarksService(StudentDbRepository _repository)
    {
        repository = _repository;
    }

    public object Get(MarksRequestDto dto)
    {
        if (dto.StudentId != default(int))
        {
            var student = repository.GetStudentById(dto.StudentId);
            var marks = repository.GetMarksByStudent(dto.StudentId);

            return new MarksGetResponseDto()
            {
                Id = student.StudentId,
                Name = student.Name,
                Class = student.CurrentClass,
                Marks = marks
            };
        }
        else if (dto.MarksId != default(int))
        {
            var marks = repository.GetMarks(dto.MarksId);
            var student = repository.GetStudentById(marks.StudentId);
            return new MarksGetResponseDto()
            {
                Id = student.StudentId,
                Name = student.Name,
                Class = student.CurrentClass,
                Marks = new List() { marks }
            };
        }
        return null;
    }

    public object Post(MarksRequestDto dto)
    {
        var nextId = StaticStudentDb.studentMarks[StaticStudentDb.studentMarks.Count() - 1].Id;
        var newStudentMarks = new Marks()
        {
            StudentId = dto.StudentId,
            MarksAwarded = dto.MarksAwarded,
            MaxMarks = dto.MaxMarks,
            Subject = dto.Subject
        };

        var id = repository.AddMarks(newStudentMarks);
        newStudentMarks.Id = id;

        return newStudentMarks;
    }

    public object Put(MarksRequestDto dto)
    {
        return repository.UpdateMarks(new Marks()
        {
            Id = dto.MarksId,
            Subject = dto.Subject,
            StudentId = dto.StudentId,
            MarksAwarded = dto.MarksAwarded,
            MaxMarks = dto.MaxMarks
        });
    }
}

Here is the MarksGetResponseDto used in the above snippet:

public class MarksGetResponseDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Class { get; set; }
    public IEnumerable Marks { get; set; }
}

Using HTTP Response

In the services we wrote till now, we are returning plain objects. ServiceStack internally wraps this data inside an HTTP response before sending it to the user. But you may want to get control over the HTTP response and send data along with a status code of your choice to the client. This can be done using IHttpResult.

Let’s refactor the Get method of the StudentService to use IHttpResult:

public IHttpResult Get(StudentRequestDto studentDto)
{
    if (studentDto.Id == default(int))
    {
        var result = new HttpResult(repository.GetStudents());
        return result;
    }
    else
    {
        var student = repository.GetStudentById(studentDto.Id);

        if (student != null)
        {
            return new HttpResult(student);
        }
        else
        {
            return new HttpError(HttpStatusCode.NotFound,"Student with id "+studentDto.Id + " doesn't exist.");

        }
    }
}

Both HttpResult and HttpResult have a number of overloaded constructors offering flexibility to set status code, response type, message and a number of other HTTP parameters of our choice.

 

Razor Views

Till now, we used the Service and Data access features of ServiceStack. Let’s complete the demo application by adding some views. ServiceStack supports Razor and markdown razor views. If you are already familiar with the Razor views in ASP.NET MVC, you don’t need to learn anything new to use the view engine of ServiceStack.

The difference between ServiceStack and MVC appears when we see the way views are rendered in these frameworks. Unlike ASP.NET MVC, ServiceStack doesn’t need a controller. Data for the view is passed from the corresponding Service method. This data is available to the view in the Model object and the view can use it for model binding. Views are rendered on the same endpoint where the service is exposed. But we can still get the data served from these endpoints by specifying format of the data in the URL.

We have already added assembly required for Razor views while installing the NuGet packages. We can start building the views now. As a first step, let’s configure Razor as a plugin on start of the application.

Plugins.Add(new RazorFormat());

By default, an application doesn’t know about the razor views. We must add some configurations in Web.config to be able to use the view engine seamlessly. Luckily, the NuGet package ServiceStack adds all the required configurations to Web.config. You can check your Web.config file to see the new configurations.

By convention, ServiceStack looks for its views under a folder named Views. So create a new folder and change its name to Views. To keep the UI consistent, let’s create a layout file. Add a new file to the Views folder and name it _Layout.cshtml. Add the following code to this file:




    @ViewBag.Title
    
    


    

Student Marks Reports of XYZ School

@RenderBody()
@RenderSection("Scripts", required: false)

Like in case of MVC, the views in ServiceStack get the dynamic object ViewBag. Here we are using it to set title of the page dynamically.

By convention, names of the Views should be same as the name of the corresponding request DTO classes. As we have two DTO classes, add two files named StudentRequestDto.cshtml and MarksRequestDto.cshtml to the Views folder. Both these files automatically extend the layout file, we don’t need to declare it anywhere.

Razor mark-up in the StudentRequestDto.cshtml view is going to be very simple, as it has to loop through the student objects and display their details along with a link to the marks page. Following is the Razor mark-up in this view:

@using StudentReports.Models
@inherits ViewPage>
 
@{
    ViewBag.Title = "Student List";
}
 
@{ foreach (var item in Model) { } }
Name City Current Class View Marks
@item.Name @item.City @item.CurrentClass View Marks

Run the application and change the address in the browser to:

http://localhost:/students

It should display the following page:

students-page

The marks page is going to be more functional than the Students list page as it has to perform fetch, add and update marks operations. On load, the page gets list of marks of the student from Get method of MarksService and this data is available in the Model object. For adding and updating marks, we will invoke the corresponding REST APIs using jQuery AJAX. Following is the mark-up in the page:

@using StudentReports.Models
@inherits ViewPage
 
@{
    ViewBag.Title = "Marks of " + Model.Name + " studying in class " + Model.Class;
}
 
Name:
@Model.Name
Class:
@Model.Class
@{ if (Model.Marks == null || Model.Marks.Count() == 0) {
No marks added for the student yet.
} else { @{ foreach (var item in Model.Marks) { } }
Subject Marks Awarded Max Marks Update
@item.Subject @item.MarksAwarded @item.MaxMarks
} }
Subject
... ...

Note: The markup has been truncated here to save some space. Please download the source code to view the complete markup.

In the layout page, we have defined an optional script section that can be used in the child pages to include custom scripts. Before executing the custom script, we would have all the libraries loaded.

Let’s write some code to add new marks for a student. By default, the add marks form is invisible to the user. On click of the Add Marks button, we need to show the form and accept inputs. When the data is successfully posted to the server, we refresh the page to see all the marks of the student. Following is the script for adding new marks within the scripts section:

@section Scripts{
    
}

Alternatively, we can bind data to the table manually to avoid refreshing the page. I used this approach to keep things simple.

Similarly, we need to write script to send a PUT request when marks are modified. I am leaving this part as an assignment. The solution is available in the downloadable code for this article.

Conclusion

I hope this article helped you to get started with ServiceStack and also got your hands dirty with it. Using ServiceStack, it is easier to build services and views and get them running on any platform of your choice. The good thing is, it doesn’t depend on any other third parties to make any of its component work. At the same time, the components in the framework are built with a vision of easier usability, speed and modularity in mind. ServiceStack is not limited to the set of features discussed in this article. We will have some more articles in future focusing on more capabilities of this great framework. I encourage you to check out the GitHub projects (github.com/ServiceStack/ ) and their official wiki (https://github.com/ServiceStack/ServiceStack/wiki) to learn more about the framework.

Download the entire source code from our GitHub Repository at bit.ly/dncm15-servicestack

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Rabi Kiran (a.k.a. Ravi Kiran) is a developer working on Microsoft Technologies at Hyderabad. These days, he is spending his time on JavaScript frameworks like AngularJS, latest updates to JavaScript in ES6 and ES7, Web Components, Node.js and also on several Microsoft technologies including ASP.NET 5, SignalR and C#. He is an active blogger, an author at SitePoint and at DotNetCurry. He is rewarded with Microsoft MVP (Visual Studio and Dev Tools) and DZone MVB awards for his contribution to the community


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Jeff Ronay on Tuesday, November 25, 2014 9:55 PM
Ravi, nice article on ServiceStack. I am using the ServiceStack framework for several large applications and it is wonderful. One question on your implementation though, I am not sure what the Repository Classes add to the solution. Inheriting from Service gives you built in access to Db and all its methods to have the service perform all CRUD operations leveraging the REST verbs GET, PUT, POST, and DELETE.  If you were to make the Repository an IRepository, and then implement using ServiceStack ORMLite calls as one concrete implementation, then I could see the Repository providing another layer of decoupling and that would make sense. I guess my reason for the question is we've built some quite complex applications without the use of the repository, and in my opinion leaving it out might present a simpler picture to the user.  What do you think?  Thanks, Jeff
Comment posted by Brent White on Wednesday, November 26, 2014 10:00 AM
There are a few problems with the steps in this article.  I'm running ServiceStack 3.9.71 in vs2013 and using the code above to define the StudentRequestDto class generates a duplicate implementation error because you're doing two full class definitions.  If you make both parts partial classes, it errors out on this line:

public partial class StudentRequestDto : IReturn<StudentResponseDto>

It says there's no class named StudentResponseDto and you give no information on what you have to do to implement that class.
Comment posted by Brent White on Wednesday, November 26, 2014 10:29 AM
There are a few problems with the steps in this article.  I'm running ServiceStack 3.9.71 in vs2013 and using the code above to define the StudentRequestDto class generates a duplicate implementation error because you're doing two full class definitions.  If you make both parts partial classes, it errors out on this line:

public partial class StudentRequestDto : IReturn<StudentResponseDto>

It says there's no class named StudentResponseDto and you give no information on what you have to do to implement that class.
Comment posted by Ravi on Wednesday, November 26, 2014 11:53 AM
Hi Jeff,

Thanks and good to know that you are using ServiceStack.

Repository class in the sample is more like a data access layer. It is a single place where all DB operations happen. If the application grows, we need to refactor it to a set of repository classes. I agree with your point of creating an interface for the repository, as it would make the service classes testable. Thanks for bringing this point.
Comment posted by Ravi on Wednesday, November 26, 2014 11:57 AM
Brent,

This step is not for the sample app. My intention was to just give an idea that you can specify return type of the service in the request DTO. If you want to specify the return type, add it to the request DTO class created in previous step and define the response DTO class with properties that you want to return from the service.
Comment posted by Chandan on Tuesday, January 6, 2015 1:57 AM
Hi Ravi,
I'm running ServiceStack 4.0.35 in vs2013.
I did installed all the components mentioned in your article step by step.
However, when I tired running the application for the first time in IIS 8 express.
I should be able to see the metadata screen. but for me, it throws forbidden exception. So to fix this issue, I changed the web.config and added 2 things

<system.web>
....
<httpHandlers>
   <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
</system.web>

<system.webServer>
  <validation validateIntegratedModeConfiguration="false" />
  <modules runAllManagedModulesForAllRequests="true"/>
  <handlers>
    <add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
  </handlers>
</system.webServer>

After doing this change i was able to view the metadata screen mentioned in your article.
Not sure whether it was my mistake or nuget was not able to configure the web.config properly.
Comment posted by Ravi on Tuesday, January 6, 2015 1:16 PM
Chandan,
I think, NuGet didn't update the configurations in web.config file. I will give it a try and see if I face the same issue.