ত্রুটি বার্তা বা ব্যতিক্রম সহ আমি কীভাবে নটফাউন্ড () IHttpActionResult ফিরিয়ে দেব?


99

আমি একটি নটফাউন্ড ফিরিয়ে দিচ্ছি IHttpActionResult, যখন আমার ওয়েবএপিপি জিইটি অ্যাকশনে কোনও কিছু পাওয়া যায় না। এই প্রতিক্রিয়াটির সাথে আমি একটি কাস্টম বার্তা এবং / অথবা ব্যতিক্রম বার্তা (যদি থাকে) প্রেরণ করতে চাই। বর্তমান ApiController'র NotFound()পদ্ধতি কে একটি বার্তা পাস একটি জমিদার প্রদান করে না।

এই কাজ করার কোন উপায় আছে কি? নাকি আমার নিজের রীতিনীতি লিখতে হবে IHttpActionResult?


আপনি কি সমস্ত খুঁজে পাওয়া ফলাফলের জন্য একই বার্তাটি ফিরে আসতে চান?
নিকোলাই সামতেলজে

@ নিকোলাইস্যামটেলজে না, পরিস্থিতি অনুসারে এটি একটি ভিন্ন বার্তা হতে পারে।
অজয় যাদব

উত্তর:


84

প্রতিক্রিয়া বার্তার আকারটি কাস্টমাইজ করতে চাইলে আপনাকে নিজের ক্রিয়া ফলাফল লিখতে হবে।

আমরা খালি ৪০৪ সেকেন্ডের মতো জিনিসগুলির জন্য বাক্সের বাইরে সর্বাধিক সাধারণ প্রতিক্রিয়া বার্তার আকার সরবরাহ করতে চেয়েছিলাম, তবে আমরা এই ফলাফলগুলি যতটা সম্ভব সরল রাখতে চেয়েছিলাম; ক্রিয়া ফলাফলগুলি ব্যবহারের অন্যতম প্রধান সুবিধা হ'ল এটি আপনার ক্রিয়াকলাপটিকে ইউনিট পরীক্ষার পক্ষে আরও সহজ করে তোলে। অ্যাকশন ফলাফলের উপর আমরা যত বেশি সম্পত্তি রেখেছি, আপনার ইউনিট পরীক্ষার তত বেশি জিনিসগুলি বিবেচনা করা দরকার যা নিশ্চিত করা যায় যে ক্রিয়া পদ্ধতিটি আপনি যা প্রত্যাশা করছেন তা করছে।

আমি প্রায়শই পাশাপাশি একটি কাস্টম বার্তা সরবরাহ করার দক্ষতাও চাই, তাই ভবিষ্যতে মুক্তির জন্য সেই ক্রিয়াটির পরিণতিটিকে সমর্থন করার জন্য আমাদের বিবেচনা করতে কোনও বাগটি নির্দ্বিধায় বোধ করুন: https://aspnetwebstack.codeplex.com/workitem/list/advanced

কর্মের ফলাফলগুলির সম্পর্কে একটি দুর্দান্ত বিষয় হ'ল আপনি কিছুটা আলাদা কিছু করতে চাইলে সর্বদা আপনার নিজের মোটামুটি সহজেই লিখতে পারেন। আপনার ক্ষেত্রে এটি আপনি কীভাবে করতে পারেন তা এখানে রয়েছে (ধরে নিই যে আপনি পাঠ্য / প্লেইনে ত্রুটি বার্তাটি চান; আপনি যদি JSON চান, আপনি বিষয়বস্তুটির সাথে কিছুটা আলাদা করতে চাই):

public class NotFoundTextPlainActionResult : IHttpActionResult
{
    public NotFoundTextPlainActionResult(string message, HttpRequestMessage request)
    {
        if (message == null)
        {
            throw new ArgumentNullException("message");
        }

        if (request == null)
        {
            throw new ArgumentNullException("request");
        }

        Message = message;
        Request = request;
    }

    public string Message { get; private set; }

    public HttpRequestMessage Request { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(Execute());
    }

    public HttpResponseMessage Execute()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(Message); // Put the message in the response body (text/plain content).
        response.RequestMessage = Request;
        return response;
    }
}

public static class ApiControllerExtensions
{
    public static NotFoundTextPlainActionResult NotFound(this ApiController controller, string message)
    {
        return new NotFoundTextPlainActionResult(message, controller.Request);
    }
}

তারপরে, আপনার ক্রিয়া পদ্ধতিতে আপনি ঠিক এর মতো কিছু করতে পারেন:

public class TestController : ApiController
{
    public IHttpActionResult Get()
    {
        return this.NotFound("These are not the droids you're looking for.");
    }
}

যদি আপনি একটি কাস্টম নিয়ন্ত্রক বেস ক্লাস ব্যবহার করেন (সরাসরি এপিআইআর কনট্রোলারের উত্তরাধিকার সূত্রে প্রাপ্ত হয়) তবে আপনি "এটি "ও মুছে ফেলতে পারেন। অংশ (যা কোনও এক্সটেনশন পদ্ধতি কল করার সময় দুর্ভাগ্যক্রমে প্রয়োজনীয়):

public class CustomApiController : ApiController
{
    protected NotFoundTextPlainActionResult NotFound(string message)
    {
        return new NotFoundTextPlainActionResult(message, Request);
    }
}

public class TestController : CustomApiController
{
    public IHttpActionResult Get()
    {
        return NotFound("These are not the droids you're looking for.");
    }
}

4
আমি 'IHttpActionResult' এর ঠিক একই রকম প্রয়োগটি লিখেছি, তবে 'নটফাউন্ড' ফলাফলের জন্য নির্দিষ্ট নয়। এটি সম্ভবত সমস্ত 'এইচটিপিস্ট্যাটাসকোডস' এর জন্য কাজ করবে। আমার CustomActionResult কোড ভালো কিছু দেখায় এই আমার নিয়ন্ত্রক এর 'পান ()' এই মত কর্ম দেখায়: পাবলিক IHttpActionResult পান () {ফিরতি CustomNotFoundResult ( "। Meessage রিটার্ন করতে"); } 'এছাড়াও, আমি ভবিষ্যতে প্রকাশে এটি বিবেচনা করার জন্য কোডপ্লেক্সে একটি বাগ লগ করেছি ।
অজয় যাদব

আমি ওডাটা কন্ট্রোলার ব্যবহার করি এবং আমাকে এটি ব্যবহার করতে হয়েছিল ot নটফাউন্ড ("ব্লাহ");
জেরেथर

4
খুব সুন্দর পোস্ট, তবে আমি উত্তরাধিকার পরামর্শের বিরুদ্ধে পরামর্শ দিতে চাই। আমার দল দীর্ঘদিন আগে ঠিক এমনটি করার সিদ্ধান্ত নিয়েছিল এবং এটি করে ক্লাসগুলি অনেকটা ফুলে যায়। আমি সবে সম্প্রতি এগুলির সমস্তটিকে এক্সটেনশন পদ্ধতিতে রিফেক্টর করেছি এবং উত্তরাধিকার শৃঙ্খলা থেকে সরে এসেছি। আমি কখনই লোকেরা এই জাতীয় উত্তরাধিকার ব্যবহার করা উচিত সাবধানতার সাথে বিবেচনা করার পরামর্শ দিই। সাধারণত, রচনাটি আরও অনেক ভাল, কারণ এটি অনেক বেশি ডিকোপলড।
জুলাইগলন

6
এই কার্যকারিতাটি বাক্সের বাইরে হওয়া উচিত ছিল। Alচ্ছিক "রেসপন্সবডি" প্যারামিটার সহ ইউনিট-টেস্টগুলিকে প্রভাবিত করা উচিত নয়।
থিওডোর জোগোগ্রস

235

একটি সাধারণ বার্তা সহ IHttpActionResult নটফাউন্ড ফিরিয়ে দেওয়ার জন্য এখানে একটি ওয়ান-লাইনার রয়েছে:

return Content(HttpStatusCode.NotFound, "Foo does not exist.");

24
লোকদের এই উত্তরটি দেওয়া উচিত। এটি সুন্দর এবং সহজ!
জেস

4
সচেতন হন যে এই সমাধানটি HTTP শিরোনামের স্থিতিটি "404 পাওয়া যায় নি" তে সেট করে না।
ক্যাস্পার হালভাস জেনসেন

4
@ ক্যাস্পারহালবাসজেনসেন সার্ভারের এইচটিসিপি স্থিতি কোডটি 404, আপনার কি আরও কিছু প্রয়োজন?
অ্যান্থনি এফ

4
পছন্দ করুন আমি কন্ট্রোলারআর কনটেন্ট (...) ব্যবহার করছিলাম। শোড ApiController.Content (...) ব্যবহার করেছেন - আমার খারাপ।
ক্যাস্পার হালভাস জেনসেন


28

আপনি চাইলে ব্যবহার ResponseMessageResultকরতে পারেন:

var myCustomMessage = "your custom message which would be sent as a content-negotiated response"; 
return ResponseMessage(
    Request.CreateResponse(
        HttpStatusCode.NotFound, 
        myCustomMessage
    )
);

হ্যাঁ, আপনার যদি আরও সংক্ষিপ্ত সংস্করণ প্রয়োজন হয় তবে আমার ধারণা আপনার কাস্টম অ্যাকশন ফলাফলটি কার্যকর করা দরকার।


ঝরঝরে মনে হচ্ছিল আমি এই পদ্ধতিটি দিয়ে চলেছি। আমি স্রেফ অন্যত্র কাস্টম বার্তা এবং ইন্টেন্টেড রিটার্ন কোড সংজ্ঞায়িত করেছি।
ozzy432836

আমি বিষয়বস্তুর চেয়ে এটিকে আরও ভাল পছন্দ করি কারণ এটি আসলে এমন কোনও বস্তু ফেরত দেয় যা আমি স্ট্যান্ডার্ড BadRequest পদ্ধতির মতো একটি বার্তা সম্পত্তি দিয়ে পার্স করতে পারি।
ব্যবহারকারী 1568891

7

আপনি HttpResponseMessage শ্রেণীর রিজনফ্রেস সম্পত্তি ব্যবহার করতে পারেন

catch (Exception exception)
{
  throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)
  {
    ReasonPhrase = exception.Message
  });
}

ধন্যবাদ ঠিক আছে .. এটি কাজ করা উচিত, তবে তারপরে আমাকে প্রতিটি ক্রিয়ায় আমার নিজের থেকে HTTPResponseException তৈরি করতে হবে। কোডটি কম রাখার জন্য, আমি ভাবছিলাম যে আমি যদি কোনও ওয়েবএপিআই 2 বৈশিষ্ট্য (যেমন প্রস্তুত নোটফাউন্টের মতো ) , ঠিক আছে () পদ্ধতিগুলি ব্যবহার করতে পারি এবং এটিতে যুক্তিফ্র্যাস বার্তাটি পাস করতে পারি।
অজয় যাদব

আপনি নিজের এক্সটেনশন পদ্ধতি নটফাউন্ড (ব্যতিক্রম ব্যতিক্রম) তৈরি করতে পারেন, যা সঠিক HTTPResponseException নিক্ষেপ করবে
Dmytro Rudenko

@ ডমিট্রো রুডেনকো: পরীক্ষার যোগ্যতা উন্নত করতে কর্মের ফলাফল প্রবর্তিত হয়েছিল। এখানে HTTPResponseException নিক্ষেপ করে আপনি এটি আপস করবেন। এছাড়াও এখানে আমাদের কোনও ব্যতিক্রম নেই, তবে ওপি একটি বার্তা প্রেরণের জন্য সন্ধান করছে।
কিরণ চালা

ঠিক আছে, আপনি যদি পরীক্ষার জন্য NUint ব্যবহার করতে না চান তবে আপনি নোটফাউন্ডআরসাল্টের নিজস্ব প্রয়োগটি লিখতে পারেন এবং আপনার বার্তার ডেটা ফেরত দেওয়ার জন্য এর এক্সিকিউটিএসিঙ্কটি পুনরায় লিখতে পারেন। আপনার ক্রিয়াকলাপের অনুরোধের ফলস্বরূপ এই শ্রেণীর ফেরতের উদাহরণ
Dmytro Rudenko

4
মনে রাখবেন যে আপনি এখন স্ট্যাটাস কোডটি সরাসরি পাস করতে পারবেন, যেমন: HTTPResponseException (HttpStatusCode.NotFound)
মার্ক সোউল ২

3

D3m3t3er এর পরামর্শ অনুসারে আপনি একটি কাস্টম আলোচিত সামগ্রীর ফলাফল তৈরি করতে পারেন। তবে আমি উত্তরাধিকারী হতে হবে। এছাড়াও, যদি আপনার কেবল নোটফাউন্ড ফিরিয়ে দেওয়ার জন্য এটির প্রয়োজন হয় তবে আপনাকে কনস্ট্রাক্টর থেকে http স্থিতি আরম্ভ করার দরকার নেই।

public class NotFoundNegotiatedContentResult<T> : NegotiatedContentResult<T>
{
    public NotFoundNegotiatedContentResult(T content, ApiController controller)
        : base(HttpStatusCode.NotFound, content, controller)
    {
    }

    public override Task<HttpResponseMessage> ExecuteAsync(
        CancellationToken cancellationToken)
    {
        return base.ExecuteAsync(cancellationToken).ContinueWith(
            task => task.Result, cancellationToken);
    }
}

2

OkNegotiatedContentResultফলস্বরূপ প্রতিক্রিয়া বার্তায় HTTP কোডটি উত্পন্ন করে ও ওভাররাইড করে আমি এটিকে সমাধান করেছি । এই শ্রেণিটি আপনাকে যে কোনও এইচটিটিপি প্রতিক্রিয়া কোড সহ সামগ্রী সামগ্রী ফেরত দিতে দেয়।

public class CustomNegotiatedContentResult<T> : OkNegotiatedContentResult<T>
{
    public HttpStatusCode HttpStatusCode;

    public CustomNegotiatedContentResult(
        HttpStatusCode httpStatusCode, T content, ApiController controller)
        : base(content, controller)
    {
        HttpStatusCode = httpStatusCode;
    }

    public override Task<HttpResponseMessage> ExecuteAsync(
        CancellationToken cancellationToken)
    {
        return base.ExecuteAsync(cancellationToken).ContinueWith(
            task => { 
                // override OK HTTP status code with our own
                task.Result.StatusCode = HttpStatusCode;
                return task.Result;
            },
            cancellationToken);
    }
}

2

সম্পত্তিটি সেট করার জন্য আমার IHttpActionResultকোনও IExceptionHandlerশ্রেণীর শরীরে একটি উদাহরণ তৈরি করা দরকার ছিল ExceptionHandlerContext.Result। তবে আমি একটি কাস্টম সেট করতে চেয়েছিলামReasonPhrase

আমি খুঁজে পেয়েছি যে একটি একটি ResponseMessageResultমোড়ানো পারেHttpResponseMessage মোড়তে পারে (যা রিজনফ্রেস সহজেই সেট করার অনুমতি দেয়)।

উদাহরণ স্বরূপ:

public class MyExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        var ex = context.Exception as IRecordNotFoundException;
        if (ex != null)
        {
            context.Result = new ResponseMessageResult(new HttpResponseMessage(HttpStatusCode.NotFound) { ReasonPhrase = $"{ex.EntityName} not found" });
        }
    }
}

1

যদি আপনি বেস NegotitatedContentResult<T>হিসাবে উত্তরাধিকারসূত্রে প্রাপ্ত হন, এবং আপনার নিজের রূপান্তর করার দরকার নেই content(উদাহরণস্বরূপ আপনি কেবল একটি স্ট্রিং ফিরিয়ে দিতে চান), তবে আপনাকে ওভাররাইড করার দরকার নেইExecuteAsync পদ্ধতিটি ।

আপনাকে যা করতে হবে তা হ'ল একটি উপযুক্ত ধরণের সংজ্ঞা এবং একটি নির্মাতা সরবরাহ করুন যা HTTP স্থিতি কোডটি ফিরে আসতে হবে সেই বেসটি বলে। অন্য সব কিছুই ঠিক কাজ করে।

এখানে উভয়ের জন্য উদাহরণ NotFoundএবং InternalServerError:

public class NotFoundNegotiatedContentResult : NegotiatedContentResult<string>
{
    public NotFoundNegotiatedContentResult(string content, ApiController controller)
        : base(HttpStatusCode.NotFound, content, controller) { }
}

public class InternalServerErrorNegotiatedContentResult : NegotiatedContentResult<string>
{
    public InternalServerErrorNegotiatedContentResult(string content, ApiController controller)
        : base(HttpStatusCode.InternalServerError, content, controller) { }
}

এবং তারপরে আপনি এর জন্য প্রাসঙ্গিক এক্সটেনশন পদ্ধতি তৈরি করতে পারেন ApiController(বা যদি আপনার কাছে থাকে তবে এটি বেস শ্রেণিতে করুন):

public static NotFoundNegotiatedContentResult NotFound(this ApiController controller, string message)
{
    return new NotFoundNegotiatedContentResult(message, controller);
}

public static InternalServerErrorNegotiatedContentResult InternalServerError(this ApiController controller, string message)
{
    return new InternalServerErrorNegotiatedContentResult(message, controller);
}

এবং তারপরে তারা বিল্ট-ইন পদ্ধতিগুলির মতোই কাজ করে। আপনি হয় বিদ্যমান NotFound()কল করতে পারেন বা আপনি আপনার নতুন কাস্টম কল করতে পারেন NotFound(myErrorMessage)

এবং অবশ্যই, আপনি কাস্টম প্রকারের সংজ্ঞাগুলিতে "হার্ড কোডিং" স্ট্রিং প্রকারগুলি থেকে মুক্তি পেতে পারেন এবং আপনি যদি চান তবে জেনেরিক রেখে যেতে পারেন তবে তার উপর নির্ভর করে আপনার স্টাফ নিয়ে চিন্তিত হতে পারেExecuteAsync<T> আসলে ।

তোমাদের উপর সন্ধান করতে পারেন সোর্স কোড জন্য NegotiatedContentResult<T>সব এটা আছে দেখতে। এটির তেমন কিছুই নেই।


0

অজানা পিও একটি বার্তার পাঠ্য সহ জিজ্ঞাসা করেছিল, তবে কেবল 404 ফেরত দেওয়ার জন্য অন্য বিকল্পটি পদ্ধতিটিকে একটি আইএইচটিপিএকশনরেসাল্ট ফিরিয়েছে এবং স্ট্যাটাসকোড ফাংশনটি ব্যবহার করছে

    public async Task<IHttpActionResult> Get([FromUri]string id)
    {
       var item = await _service.GetItem(id);
       if(item == null)
       {
           StatusCode(HttpStatusCode.NotFound);
       }
       return Ok(item);
    }

0

এখানে উত্তরগুলি একটু বিকাশকারী গল্পের সমস্যা অনুপস্থিত। ApiControllerবর্গ এখনও একটি প্রকাশক হয়NotFound() পদ্ধতি যা ডেভেলপারদের ব্যবহার করতে পারে। এটি একটি অনিয়ন্ত্রিত ফলাফলের শরীরকে ধারণ করতে প্রায় 404 প্রতিক্রিয়া সৃষ্টি করবে।

আমি এখানে কোডের কয়েকটি অংশ " আরও ভাল অ্যাপিকন্ট্রোলার নটফাউন্ড পদ্ধতি " উপস্থাপন করেছি যা কম ত্রুটি-প্রবণ পদ্ধতি সরবরাহ করবে যা বিকাশকারীদের "404 প্রেরণের আরও ভাল উপায়" জানতে হবে না।

  • একটি বর্গ তৈরি থেকে উত্তরাধিকার সূত্রে প্রাপ্তApiController নামকApiController
    • আমি বিকাশকারীদের মূল ক্লাস ব্যবহার থেকে বিরত রাখতে এই কৌশলটি ব্যবহার করি
  • NotFoundডেভগুলিকে প্রথম উপলব্ধ এপিআই ব্যবহার করতে দেয়ার জন্য তার পদ্ধতিটি ওভাররাইড করুন
  • আপনি যদি নিরুৎসাহিত করতে চান তবে এটি হিসাবে চিহ্নিত করুন [Obsolete("Use overload instead")]
  • protected NotFoundResult NotFound(string message)আপনি উত্সাহ দিতে চান একটি অতিরিক্ত যোগ করুন
  • সমস্যা: ফলাফল একটি শরীরের সাথে প্রতিক্রিয়া সমর্থন করে না। সমাধান: উত্তরাধিকারী এবং ব্যবহার NegotiatedContentResult। আরও ভাল সংযুক্ত নটফাউন্ডআরসাল্ট ক্লাস দেখুন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.