ServiceStack POST 空体的招摇招摇、ServiceStack、POST

由网友(与幸福有约)分享简介:我在使用 )在上个月内,所以我认为它在 Nuget 下载中不可用.您看到的是一个空的正文,因为您的 DTO 上的每个属性的 ParameterType 都是正文".Swagger 想要一个包含整个请求正文内容的正文"值.它不会循环遍历您的每个正文"属性来组成正文内容.如果您填充 Rating 文本框,您应该会在请求中看...

我在使用 )在上个月内,所以我认为它在 Nuget 下载中不可用.

您看到的是一个空的正文,因为您的 DTO 上的每个属性的 ParameterType 都是正文".Swagger 想要一个包含整个请求正文内容的正文"值.它不会循环遍历您的每个正文"属性来组成正文内容.如果您填充 Rating 文本框,您应该会在请求中看到它的值(Rating 是您的最后一个带有 'body' ParameterType 的属性).

招摇 挖坑不填坑的节奏,剧情新颖却不够严谨

在此处查看示例 http://petstore.swagger.wordnik.com/#!/pet/addPet_post_1

使用 Chrome 或 Firebug,您可以在 swagger-ui.js 中的第 1182 行周围设置断点,以查看它如何构建请求正文内容(bodyParam 变量)

I'm having some problems with the Swagger plugin to ServiceStack. I have configured the route descriptions for my service, but the resulting POST does not contain a body.

My Service looks like this:

/// <summary>
/// Define your ServiceStack web service request (i.e. Request DTO).
/// </summary>
/// <remarks>The route is defined here rather than in the AppHost.</remarks>
[Api("GET or DELETE a single movie by Id. Use POST to create a new Movie and PUT to update it")]
[Route("/movie", "POST", Summary = @"POST a new movie", Notes = "Send a movie here")]
[Route("/movie/{Id}", "GET,PUT,DELETE", Summary = @"GET, PUT, or DELETE a movie", Notes = "GET a specific movie by Id, or PUT a thing, or delete a movie")]
public class Movie
{
    /// <summary>
    /// Initializes a new instance of the movie.
    /// </summary>
    public Movie()
    {
        this.Genres = new List<string>();
    }

    /// <summary>
    /// Gets or sets the id of the movie. The id will be automatically incremented when added.
    /// </summary>
    //[AutoIncrement]
    [ApiMember(Name = "Id", Description = "The Id of this movie", ParameterType = "body", DataType = "string", IsRequired = false)]
    public string Id { get; set; }

    [ApiMember(Name = "ImdbId", Description = "The ImdbId of this movie", ParameterType = "body", DataType = "string", IsRequired = false)]
    public string ImdbId { get; set; }

    [ApiMember(Name = "Title", Description = "The Title of this movie", ParameterType = "body", DataType = "string", IsRequired = false)]
    public string Title { get; set; }

    [ApiMember(Name = "Rating", Description = "The Rating of this movie", ParameterType = "body", DataType = "decimal", IsRequired = false)]
    public decimal Rating { get; set; }

    [ApiMember(Name = "Director", Description = "The Director of this movie", ParameterType = "string", DataType = "string", IsRequired = false)]
    public string Director { get; set; }

    [ApiMember(Name = "ReleaseDate", Description = "The ReleaseDate of this movie", ParameterType = "string", DataType = "Date", IsRequired = false)]
    public DateTime ReleaseDate { get; set; }

    [ApiMember(Name = "TagLine", Description = "The TagLine of this movie", ParameterType = "string", DataType = "string", IsRequired = false)]
    public string TagLine { get; set; }

    [ApiMember(Name = "Genres", Description = "The Genres of this movie", ParameterType = "string", DataType = "string", IsRequired = false)]
    public List<string> Genres { get; set; }
}

/// <summary>
/// Define your ServiceStack web service response (i.e. Response DTO).
/// </summary>
public class MovieResponse
{
    /// <summary>
    /// Gets or sets the movie.
    /// </summary>
    public Movie Movie { get; set; }
}

/// <summary>
/// Create your ServiceStack restful web service implementation. 
/// </summary>
public class MovieService : Service
{
    public IMovieRepository MovieRepository { get; set; }

    /// <summary>
    /// GET /movies/{Id} 
    /// </summary>
    public MovieResponse Get(Movie movie)
    {
        var item = MovieRepository.FindOne(new ObjectId(movie.Id));

        return new MovieResponse
        {
            Movie = item,
        };
    }

    /// <summary>
    /// POST /movies
    /// 
    /// returns HTTP Response => 
    ///     201 Created
    ///     Location: http://localhost/ServiceStack.MovieRest/movies/{newMovieId}
    ///     
    ///     {newMovie DTO in [xml|json|jsv|etc]}
    /// 
    /// </summary>
    public object Post(Movie movie)
    {
        MovieRepository.Save(movie);
        var newMovieId = movie.Id;

        var newMovie = new MovieResponse
        {
            Movie = MovieRepository.FindOne(new ObjectId(movie.Id))
        };

        return new HttpResult(newMovie)
        {
            StatusCode = HttpStatusCode.Created,
            Headers = {
                { HttpHeaders.Location, base.Request.AbsoluteUri.CombineWith(newMovieId) }
            }
        };
    }

    /// <summary>
    /// PUT /movies/{id}
    /// </summary>
    public object Put(Movie movie)
    {
        MovieRepository.Save(movie);

        return new HttpResult
        {
            StatusCode = HttpStatusCode.NoContent,
            Headers = {
                { HttpHeaders.Location, this.RequestContext.AbsoluteUri.CombineWith(movie.Id) }
            }
        };
    }

    /// <summary>
    /// DELETE /movies/{Id}
    /// </summary>
    public object Delete(Movie request)
    {
        MovieRepository.Remove(new ObjectId(request.Id));

        return new HttpResult
        {
            StatusCode = HttpStatusCode.NoContent,
            Headers = {
                { HttpHeaders.Location, this.RequestContext.AbsoluteUri.CombineWith(request.Id) }
            }
        };
    }
}

/// <summary>
/// Define your ServiceStack web service request (i.e. Request DTO).
/// </summary>
/// <remarks>The route is defined here rather than in the AppHost.</remarks>
[Api("Find movies by genre, or all movies if no genre is provided")]
[Route("/movies", "GET, OPTIONS")]
[Route("/movies/genres/{Genre}")]
public class Movies
{
    public string Genre { get; set; }
}

/// <summary>
/// Define your ServiceStack web service response (i.e. Response DTO).
/// </summary>    
public class MoviesResponse
{
    /// <summary>
    /// Gets or sets the list of movies.
    /// </summary>

    public List<Movie> Movies { get; set; }
}

/// <summary>
/// Create your ServiceStack RESTful web service implementation. 
/// </summary>
public class MoviesService : Service
{
    public IMovieRepository MovieRepository { get; set; }

    /// <summary>
    /// GET /movies 
    /// GET /movies/genres/{Genre}
    /// </summary>
    public object Get(Movies request)
    {
        return new MoviesResponse
        {
            Movies = MovieRepository.FindAll().ToList()
        };
    }
}

The Swagger interface appears to have picked up the elements correctly:

The results is a 500 error:

POST http://localhost:57853/movie HTTP/1.1
Host: localhost:57853
Connection: keep-alive
Content-Length: 0
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:57853
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17
Content-Type: application/json
Referer: http://localhost:57853/swagger-ui/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

The POST body is not attached by Swagger. The Content-Length:0. The results is an empty request object, which results in a NullReferenceException.

Can anyone see anything that I am doing wrong?

解决方案

A couple issues I see...

I think you're trying to mimic a Form post using Swagger-UI. This feature was just added to swagger (https://github.com/wordnik/swagger-core/issues/69) within the last month so I don't think it's available in the Nuget download.

You're seeing an empty body because your ParameterType is 'body' for each Property on your DTO. Swagger wants a single 'body' value which should contain the entire request body contents. It is not looping through each of your 'body' properties to compose the body contents. If you populate the Rating text box you should see it's value in the request (Rating is your last property with 'body' ParameterType).

see example here http://petstore.swagger.wordnik.com/#!/pet/addPet_post_1

Using Chrome or Firebug you can set a breakpoint around line #1182 in swagger-ui.js to see how it's building up the request body contents (bodyParam variable)

阅读全文

相关推荐

最新文章