ওয়েব এপিআই নিয়ামক থেকে HTTP স্থিতি কোড ফেরত


219

আমি ওয়েব এপিআই কন্ট্রোলারে কোনও জিইটি পদ্ধতির জন্য সংশোধিত না হয়ে 304 এর স্থিতি কোডটি ফিরিয়ে দেওয়ার চেষ্টা করছি।

আমি সফল হওয়ার একমাত্র উপায় ছিল এরকম কিছু:

public class TryController : ApiController
{
    public User GetUser(int userId, DateTime lastModifiedAtClient)
    {
        var user = new DataEntities().Users.First(p => p.Id == userId);
        if (user.LastModified <= lastModifiedAtClient)
        {
             throw new HttpResponseException(HttpStatusCode.NotModified);
        }
        return user;
    }
}

এখানে সমস্যাটি হ'ল এটি কোনও ব্যতিক্রম নয়, ক্লায়েন্ট ক্যাশে ঠিক আছে তাই এটি কেবল সংশোধিত হয়নি। আমিও চাই যে রিটার্নের ধরনটি একজন ব্যবহারকারী হয়ে উঠুক (যেমন সমস্ত ওয়েব এপিআই উদাহরণগুলি জিইটি-র সাথে দেখায়) এইচটিটিপিআরস্পোনমেসেজ বা এর মতো কিছু না ফেরায়।


আপনি ব্যবহার করছেন betaবা রাতে নির্মাণ ?
আলিওস্টাড

@ আলিওস্টাড আমি বিটা ব্যবহার করছি
ওজবা

তো ফিরতে দোষ কী new HttpResponseMessage(HttpStatusCode.NotModified)? এটা কি কাজ করে না?
অলিওস্টাড

@ আলিওস্টাড আমি ফিরতি টাইপ ব্যবহারকারী হওয়ার সময় এইচটিপিআরএসপোনস ম্যাসেজটি ফিরিয়ে দিতে পারি না, এটি সংকলন করছে না (স্পষ্টতই)।
ওজবা

উত্তর:


251

আমি উত্তরটি জানি না তাই এএসপি.এনইটি টিমকে এখানে জিজ্ঞাসা করলেন ।

সুতরাং কৌশলটি হ'ল স্বাক্ষরটি পরিবর্তন করতে HttpResponseMessageএবং ব্যবহার করতে Request.CreateResponse

[ResponseType(typeof(User))]
public HttpResponseMessage GetUser(HttpRequestMessage request, int userId, DateTime lastModifiedAtClient)
{
    var user = new DataEntities().Users.First(p => p.Id == userId);
    if (user.LastModified <= lastModifiedAtClient)
    {
         return new HttpResponseMessage(HttpStatusCode.NotModified);
    }
    return request.CreateResponse(HttpStatusCode.OK, user);
}

3
এটি এএসপি.নেট এমভিসি 4 বিটা রিলিজে সংকলন করে না, কারণ ক্রিয়েটরেসপন্স প্যারামিটার হিসাবে কেবল স্থিতি কোড নেয়। দ্বিতীয়ত আমি কোনও HTTPResponseMessage ছাড়াই সমাধানটি চেয়েছিলাম যেহেতু এটি প্রত্যাখ্যানিত হওয়ায় রিটার্ন মান হিসাবে: এস্পনেটবেসটাক কোডডপ্লেক্স
ডিসকশন

5
যদি কারও এটির প্রয়োজন হয় তবে কন্ট্রোলার পদ্ধতি থেকে মানটি পাওয়া GetUser(request, id, lastModified).TryGetContentValue(out user), যেখানে user(উদাহরণস্বরূপ) একটি Userবস্তু।
গ্রিন

4
2015 এ কি এটি এখনও পছন্দসই পদ্ধতি? এমভিসি 5?
ক্রাশ করুন

4
আরও আধুনিক সংস্করণটি IHttpActionResult দেয় - HttpResponseMessage (2017) নয়
নিকো

8
নিাইকোর পরামর্শ যোগ করতে, যখন ফিরতি টাইপ হয় IHttpActionResultএবং আপনি ব্যবহারকারীকে ফিরিয়ে দিতে চান, আপনি কেবল এটি করতে পারেন return Ok(user)। যদি আপনাকে অন্য স্থিতি কোডটি ফেরত দিতে হয় (তবে, নিষিদ্ধ) আপনি ঠিক করতে পারেন return this.StatusCode(HttpStatusCode.Forbidden)
ড্র

68

আপনি যদি ফেরত ব্যবহারকারীর হিসাবে অ্যাকশন স্বাক্ষর সংরক্ষণ করতে চান তবে আপনি নিম্নলিখিতগুলিও করতে পারেন:

public User GetUser(int userId, DateTime lastModifiedAtClient) 

200তারপরে যদি আপনি অন্য কোনও কিছু ফিরে আসতে চান তবে আপনি নিজের ক্রিয়াকলাপটি ছুঁড়ে ফেলুন HttpResponseExceptionএবং HttpResponseMessageক্লায়েন্টের কাছে পাঠাতে চান এমনটি পাস করুন।


9
এটি একটি উপায় আরও মার্জিত সমাধান (আলবাইট অসম্পূর্ণ উত্তর)। সকলেই কেন কঠোর উপায়ে এটি করতে পছন্দ করছেন?
নাগ্যিচেক

4
@Geoist stackoverflow.com/questions/1282252/... । ব্যতিক্রম ছোঁড়া ব্যয়বহুল।
টিয়া

10
হ্যাঁ, আপনি যদি একটি ব্যস্ত এপিআই ডিজাইন করেন, তবে সর্বাধিক সাধারণ ক্ষেত্রে যোগাযোগ করার জন্য ব্যতিক্রম ব্যবহার করে NotModifiedনিরর্থক। যদি আপনার সমস্ত API গুলি এটি করে থাকে তবে আপনার সার্ভারটি বেশিরভাগ ক্ষেত্রেই ওয়াটগুলিকে ব্যতিক্রমে রূপান্তর করবে।
লুক পুপলেট

2
@ নাগাইটেক কারণ আপনি কোনও ত্রুটি (400 উত্তর হিসাবে) ফেলে দিলে আপনি একটি কাস্টম ত্রুটি বার্তাটি ফেরত দিতে পারবেন না ... এছাড়াও কোডটি প্রত্যাশা করা এমন কিছুর জন্য ব্যতিক্রম নিক্ষেপ করা বোকামি। ব্যয়বহুল এবং আপনি যখন প্রয়োজনীয়ভাবে সেগুলি চান না তখন লগ করা হবে। তারা আসলে ব্যতিক্রম নয়।
রক্লান

40

এমভিসি 5 তে, জিনিসগুলি সহজ হয়ে গেছে:

return new StatusCodeResult(HttpStatusCode.NotModified, this);

3
একটি বার্তা নির্দিষ্ট করতে পারবেন না?
ক্রাশ করুন

1
একটি বার্তা ব্যবহার করা আসলে গৃহীত উত্তর। এটি কেবলমাত্র অল্প পরিলক্ষক
জন বেটস

39

এইচটিটিপিআরএসপোনসমেসেজটি ফেরত পেতে গেটএক্সএক্সএক্সএক্স এপিআই পদ্ধতিটি পরিবর্তন করুন এবং তারপরে সম্পূর্ণ প্রতিক্রিয়াটির জন্য একটি টাইপিত সংস্করণ এবং নোটমোডাইফাইড প্রতিক্রিয়াটির জন্য টাইপ করা সংস্করণটি ফিরিয়ে দিন।

    public HttpResponseMessage GetComputingDevice(string id)
    {
        ComputingDevice computingDevice =
            _db.Devices.OfType<ComputingDevice>()
                .SingleOrDefault(c => c.AssetId == id);

        if (computingDevice == null)
        {
            return this.Request.CreateResponse(HttpStatusCode.NotFound);
        }

        if (this.Request.ClientHasStaleData(computingDevice.ModifiedDate))
        {
            return this.Request.CreateResponse<ComputingDevice>(
                HttpStatusCode.OK, computingDevice);
        }
        else
        {
            return this.Request.CreateResponse(HttpStatusCode.NotModified);
        }
    }

* ক্লায়েন্টহ্যাসস্টেল ডেটা ইটাগ এবং ইফমোডিফাইডসিন্ড শিরোনামগুলি পরীক্ষা করার জন্য আমার এক্সটেনশন।

এমভিসি কাঠামোটি এখনও আপনার ক্রিয়াকলাপটি সিরিয়ালাইজ করে ফিরতে হবে।

বিঃদ্রঃ

আমি ভাবি জেনেরিক সংস্করণটি ওয়েব এপিআইয়ের ভবিষ্যতের কিছু সংস্করণে সরানো হচ্ছে।


4
এটি হ'ল সঠিক উত্তরটি আমি খুঁজছিলাম - যদিও কোনও টাস্ক <HttpResponseMessage <T>> রিটার্নের ধরণ হিসাবে। ধন্যবাদ!
xeb

1
@ এক্সবেব - হ্যাঁ, এটি পুরোপুরি কল করার পক্ষে উপযুক্ত। Async
লুক পুপলেট

14

আমি পুরানো নিবন্ধগুলিকে ঘৃণা করতে ঘৃণা করি তবে গুগল অনুসন্ধানে এটির জন্য এটিই প্রথম ফলাফল এবং এই সমস্যাটি নিয়ে আমার একটি সময় ছিল (এমনকি আপনার লোকদের সমর্থন নিয়েও)। সুতরাং এখানে কিছুই হয় না ...

আশা করি আমার সমাধান তাদেরকে সহায়তা করবে যেগুলিও বিভ্রান্ত হয়েছিল।

namespace MyApplication.WebAPI.Controllers
{
    public class BaseController : ApiController
    {
        public T SendResponse<T>(T response, HttpStatusCode statusCode = HttpStatusCode.OK)
        {
            if (statusCode != HttpStatusCode.OK)
            {
                // leave it up to microsoft to make this way more complicated than it needs to be
                // seriously i used to be able to just set the status and leave it at that but nooo... now 
                // i need to throw an exception 
                var badResponse =
                    new HttpResponseMessage(statusCode)
                    {
                        Content =  new StringContent(JsonConvert.SerializeObject(response), Encoding.UTF8, "application/json")
                    };

                throw new HttpResponseException(badResponse);
            }
            return response;
        }
    }
}

এবং তারপরে কেবল বেসকন্ট্রোলার থেকে উত্তরাধিকারী হন

[RoutePrefix("api/devicemanagement")]
public class DeviceManagementController : BaseController
{...

এবং তারপরে এটি ব্যবহার করে

[HttpGet]
[Route("device/search/{property}/{value}")]
public SearchForDeviceResponse SearchForDevice(string property, string value)
{
    //todo: limit search property here?
    var response = new SearchForDeviceResponse();

    var results = _deviceManagementBusiness.SearchForDevices(property, value);

    response.Success = true;
    response.Data = results;

    var statusCode = results == null || !results.Any() ? HttpStatusCode.NoContent : HttpStatusCode.OK;

    return SendResponse(response, statusCode);
}

1
উজ্জ্বল। আমাকে এক টন সময় বাঁচিয়েছে।
gls123

10

.NET কোর 2.2 304 স্থিতি কোডটি ফিরিয়ে দিচ্ছে। এটি একটি অ্যাপিকন্ট্রোলার ব্যবহার করছে।

    [HttpGet]
    public ActionResult<YOUROBJECT> Get()
    {
        return StatusCode(304);
    }

Ptionচ্ছিকভাবে আপনি প্রতিক্রিয়া দিয়ে একটি বস্তু ফিরে আসতে পারেন

    [HttpGet]
    public ActionResult<YOUROBJECT> Get()
    {
        return StatusCode(304, YOUROBJECT); 
    }

7

এএসপি.নেট ওয়েব এপিআই 2 এর জন্য, এমএসের এই পোস্টটি পদ্ধতির রিটার্নের ধরনটি পরিবর্তিত করার পরামর্শ দেয় IHttpActionResult। এর পরে আপনি মধ্যে একটি অন্তর্নির্মিত আসতে পারেন IHttpActionResultমত বাস্তবায়ন Ok, BadRequest, ইত্যাদি ( এখানে দেখতে ) অথবা আপনার নিজের বাস্তবায়ন ফিরে যান।

আপনার কোডের জন্য, এটি এমনভাবে করা যেতে পারে:

public IHttpActionResult GetUser(int userId, DateTime lastModifiedAtClient)
{
    var user = new DataEntities().Users.First(p => p.Id == userId);
    if (user.LastModified <= lastModifiedAtClient)
    {
        return StatusCode(HttpStatusCode.NotModified);
    }
    return Ok(user);
}

3

অন্য বিকল্প:

return new NotModified();

public class NotModified : IHttpActionResult
{
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotModified);
        return Task.FromResult(response);
    }
}

2
public HttpResponseMessage Post(Article article)
{
    HttpResponseMessage response = Request.CreateResponse<Article>(HttpStatusCode.Created, article);

    string uriToTheCreatedItem = Url.Route(null, new { id = article.Id });
    response.Headers.Location = new Uri(Request.RequestUri, uriToTheCreatedItem);

    return response;
}

2

আপনার যদি কোনও আইএইচটিপিএকশনআরসাল্ট ফিরে আসতে হয় এবং ত্রুটি কোডটি এবং একটি বার্তা ফেরত দিতে চান তবে ব্যবহার করুন:

return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.NotModified, "Error message here"));

2

HTTPCreateResponse প্রকারটি ব্যবহার করতে আমার স্বাক্ষরটি পরিবর্তন করতে আমি পছন্দ করি না, তাই এটি লুকানোর জন্য আমি কিছুটা বর্ধিত সমাধান নিয়ে এসেছি।

public class HttpActionResult : IHttpActionResult
{
    public HttpActionResult(HttpRequestMessage request) : this(request, HttpStatusCode.OK)
    {
    }

    public HttpActionResult(HttpRequestMessage request, HttpStatusCode code) : this(request, code, null)
    {
    }

    public HttpActionResult(HttpRequestMessage request, HttpStatusCode code, object result)
    {
        Request = request;
        Code = code;
        Result = result;
    }

    public HttpRequestMessage Request { get; }
    public HttpStatusCode Code { get; }
    public object Result { get; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(Request.CreateResponse(Code, Result));
    }
}

তারপরে আপনি আপনার অ্যাপিকন্ট্রোলারের (অথবা আপনার বেস নিয়ামককে আরও ভাল) এর মতো একটি পদ্ধতি যুক্ত করতে পারেন:

protected IHttpActionResult CustomResult(HttpStatusCode code, object data) 
{
    // Request here is the property on the controller.
    return new HttpActionResult(Request, code, data);
}

তারপরে আপনি কোনও বিল্ট মেথডের মতোই এটি ফিরিয়ে দিতে পারবেন:

[HttpPost]
public IHttpActionResult Post(Model model)
{
    return model.Id == 1 ?
                Ok() :
                CustomResult(HttpStatusCode.NotAcceptable, new { 
                    data = model, 
                    error = "The ID needs to be 1." 
                });
}

0

IHttpActionResultওয়েব এপিআই 2 তে আরও বেশি মোডেন ব্যবহার করে @ অ্যালিস্টাডস উত্তরগুলির একটি আপডেট ।

https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/action-results#ihttpactionresult

public class TryController : ApiController
{
    public IHttpActionResult GetUser(int userId, DateTime lastModifiedAtClient)
    {
        var user = new DataEntities().Users.First(p => p.Id == userId);
        if (user.LastModified <= lastModifiedAtClient)
        {
            return StatusCode(HttpStatusCode.NotModified);
            // If you would like to return a Http Status code with any object instead:
            // return Content(HttpStatusCode.InternalServerError, "My Message");
        }
        return Ok(user);
    }
}

0

এটা চেষ্টা কর :

return new ContentResult() { 
    StatusCode = 404, 
    Content = "Not found" 
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.