ASP.NET ওয়েব API এ মডেলস্টেট বৈধকরণ হ্যান্ডেল করুন


106

আমি ভাবছিলাম যে আমি কীভাবে এএসপি.নেট ওয়েব এপিআইয়ের মাধ্যমে মডেল বৈধতা অর্জন করতে পারি। আমার মত আমার মডেল আছে:

public class Enquiry
{
    [Key]
    public int EnquiryId { get; set; }
    [Required]
    public DateTime EnquiryDate { get; set; }
    [Required]
    public string CustomerAccountNumber { get; set; }
    [Required]
    public string ContactName { get; set; }
}

তারপরে আমার এপিআই কন্ট্রোলারে একটি পোস্ট ক্রিয়া রয়েছে:

public void Post(Enquiry enquiry)
{
    enquiry.EnquiryDate = DateTime.Now;
    context.DaybookEnquiries.Add(enquiry);
    context.SaveChanges();
}

আমি কীভাবে যুক্ত করব if(ModelState.IsValid)এবং তারপরে ব্যবহারকারীর কাছে যেতে ত্রুটি বার্তাটি পরিচালনা করব?

উত্তর:


186

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

using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace System.Web.Http.Filters
{
    public class ValidationActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var modelState = actionContext.ModelState;

            if (!modelState.IsValid)
                actionContext.Response = actionContext.Request
                     .CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
        }
    }
}

27
নামব্যবধান এই জন্য প্রয়োজন হয় System.Net.Http, System.Net System.Web.Http.Controllersএবং System.Web.Http.Filters
ক্রিস্টোফার স্টিভেনসন


1
এমনকি ওয়েব এপিআইর উপরে [বৈধকরণ অ্যাকশনফিল্টার] না রাখলেও, এটি কোডটি কল করে এবং আমাকে খারাপ অনুরোধ জানায়।
মাইক্রোনিক্স

1
এটি উল্লেখ করা মূল্যবান যে ত্রুটিটির প্রতিক্রিয়া ফিরিয়ে দেওয়া ইনক্লুডেররর ডেটাটেলপলিসি দ্বারা নিয়ন্ত্রিত হয় । ডিফল্টরূপে একটি দূরবর্তী অনুরোধের প্রতিক্রিয়াতে কেবল একটি জেনেরিক "একটি ত্রুটি ঘটেছে" বার্তা উপস্থিত থাকে তবে এটি সেট করার IncludeErrorDetailPolicy.Alwaysজন্য বিশদটি (আপনার ব্যবহারকারীদের কাছে বিশদ প্রকাশের ঝুঁকিতে) অন্তর্ভুক্ত থাকবে
রব

পরিবর্তে IAsyncActionFilter ব্যবহার করার পরামর্শ না দেওয়ার কোনও কারণ রয়েছে কি?
রাভিয়ার

30

আপনি যা খুঁজছিলেন তা নাও হতে পারে তবে কারও পক্ষে জানা ভাল:

আপনি যদি নেট নেট অপি 2 ব্যবহার করে থাকেন তবে আপনি কেবল নিম্নলিখিতটি করতে পারেন:

if (!ModelState.IsValid)
     return BadRequest(ModelState);

মডেল ত্রুটির উপর নির্ভর করে আপনি এই ফলাফলটি পান:

{
   Message: "The request is invalid."
   ModelState: {
       model.PropertyA: [
            "The PropertyA field is required."
       ],
       model.PropertyB: [
             "The PropertyB field is required."
       ]
   }
}

1
মনে মনে
উদ্রেক

বৈশিষ্ট্যগুলি alচ্ছিক হিসাবে চিহ্নিত করার বিষয়ে নিশ্চিত হন, অন্যথায় আপনি একটি অ-সহায়ক জেনেরিক পাবেন "একটি ত্রুটি ঘটেছে।" ভুল বার্তা.
বুকে

1
বার্তা পরিবর্তন করার কোনও উপায় আছে?
সাকিব আদিল

28

এটি পছন্দ করুন, উদাহরণস্বরূপ:

public HttpResponseMessage Post(Person person)
{
    if (ModelState.IsValid)
    {
        PersonDB.Add(person);
        return Request.CreateResponse(HttpStatusCode.Created, person);
    }
    else
    {
        // the code below should probably be refactored into a GetModelErrors
        // method on your BaseApiController or something like that

        var errors = new List<string>();
        foreach (var state in ModelState)
        {
            foreach (var error in state.Value.Errors)
            {
                errors.Add(error.ErrorMessage);
            }
        }
        return Request.CreateResponse(HttpStatusCode.Forbidden, errors);
    }
}

এটি এর মতো প্রতিক্রিয়া ফিরিয়ে দেবে (ধরে নিচ্ছে জেএসওন, তবে এক্সএমএলের একই মূল নীতি):

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
(some headers removed here)

["A value is required.","The field First is required.","Some custom errorm essage."]

আপনি অবশ্যই আপনার ত্রুটিযুক্ত অবজেক্টটি তৈরি করতে পারেন / আপনার পছন্দ মতো কোনও তালিকা তৈরি করতে পারেন, উদাহরণস্বরূপ ক্ষেত্রের নাম যুক্ত করা, ফিল্ড আইডি ইত্যাদি etc.

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

এই কাজ করতে সবচেয়ে ভালো উপায় ব্যবহার করছে ভাল পুরানো HTTP স্থিতি কোড মত 200 OKইত্যাদি। আপনার জাভাস্ক্রিপ্ট সঠিক কলব্যাকস (ত্রুটি, সাফল্য ইত্যাদি) ব্যবহার করে ব্যর্থতাগুলি সঠিকভাবে পরিচালনা করতে পারে।

একটি অ্যাকশন ফিল্টার এবং jQuery ব্যবহার করে এই পদ্ধতির আরও উন্নত সংস্করণে এখানে একটি সুন্দর টিউটোরিয়াল: http://asp.net/web-api/videos/getting-started/custom-validation


এটি কেবল আমার enquiryবস্তুটি ফেরত দেয়, এটি বলে না যে কোন সম্পত্তি যদিও অবৈধ? সুতরাং আমি যদি CustomerAccountNumberখালি ছেড়ে চলে যাই তবে এটির জন্য ডিফল্ট বৈধতা বার্তাটি বলা উচিত (CusomterAccountNumber ক্ষেত্র প্রয়োজন ..)
কলমভাস

আমি দেখতে পাচ্ছি, তাহলে মডেল বৈধকরণকে পরিচালনা করার এটি কি "সঠিক" উপায়? আমার কাছে কিছুটা অগোছালো মনে হচ্ছে ..
কলমভাস

এটি করার অন্যান্য উপায় রয়েছে, যেমন jQuery বৈধকরণের সাথে জড়িত। মাইক্রোসফ্টের একটি দুর্দান্ত উদাহরণ এখানে দেওয়া হয়েছে: asp.net/web-api/videos/getting-st সূত্র
Anders Arpi

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

এটি আমার জন্য কাজ করার জন্য আমাকে লাইনটি পরিবর্তন errors.Add(error.ErrorMessage);করতে errors.Add(error.Exception.Message);হয়েছিল।
Caltor

9

System.ComponentModel.DataAnnotationsবৈধতা নিয়ম সেট করতে আপনি নামস্থান থেকে বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন । পড়ুন মাইক Wasson দ্বারা - মডেল ভ্যালিডেশন বিস্তারিত জানার জন্য।

এছাড়াও ভিডিও এএসপি.নেট ওয়েব এপিআই, পর্ব 5: রেফারেন্স করুন কাস্টম বৈধকরণ - জন গাল্লো ay

অন্যান্য তথ্যসূত্র

  1. ওয়েবএপিআই এবং ওয়েব ফর্মগুলির সাথে ক্লায়েন্ট সাইড এ ওয়াক করুন
  2. কীভাবে এএসপি.নেট ওয়েব এপিআই এইচটিটিপি বার্তাগুলিকে ডোমেন মডেলগুলিতে আবদ্ধ করে এবং ওয়েব এপিআইতে মিডিয়া ফর্ম্যাটগুলির সাথে কীভাবে কাজ করবে।
  3. ডোমিনিক বাইয়ার - এএসপি.নেট ওয়েব এপিআইগুলি সুরক্ষিত করা
  4. এএসপি.এনইটি ওয়েব এপিআই বৈধকরণে অ্যাঙ্গুলারজেএসের বৈধকরণ হুকিং
  5. এএসপি.নেট এমভিসিতে অ্যাঙ্গুলারজেএসের সাথে মডেলস্টেট ত্রুটিগুলি প্রদর্শন করা হচ্ছে
  6. ক্লায়েন্টকে ত্রুটিগুলি কীভাবে রেন্ডার করবেন? AngularJS / WebApi ModelState
  7. ওয়েব এপিআই তে নির্ভরতা-ইনজেক্ট বৈধকরণ

8

অথবা, আপনি যদি আপনার অ্যাপ্লিকেশনগুলির জন্য ত্রুটির সাধারণ সংগ্রহের সন্ধান করছেন .. এটি আমার বাস্তবায়ন এখানে:

public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var modelState = actionContext.ModelState;

        if (!modelState.IsValid) 
        {

            var errors = new List<string>();
            foreach (var state in modelState)
            {
                foreach (var error in state.Value.Errors)
                {
                    errors.Add(error.ErrorMessage);
                }
            }

            var response = new { errors = errors };

            actionContext.Response = actionContext.Request
                .CreateResponse(HttpStatusCode.BadRequest, response, JsonMediaTypeFormatter.DefaultMediaType);
        }
    }

ত্রুটির বার্তার প্রতিক্রিয়া দেখতে পাবেন:

{
  "errors": [
    "Please enter a valid phone number (7+ more digits)",
    "Please enter a valid e-mail address"
  ]
}

5

Startup.cs ফাইলে কোডের নীচে যুক্ত করুন

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = (context) =>
                {
                    var errors = context.ModelState.Values.SelectMany(x => x.Errors.Select(p => new ErrorModel()
                   {
                       ErrorCode = ((int)HttpStatusCode.BadRequest).ToString(CultureInfo.CurrentCulture),
                        ErrorMessage = p.ErrorMessage,
                        ServerErrorMessage = string.Empty
                    })).ToList();
                    var result = new BaseResponse
                    {
                        Error = errors,
                        ResponseCode = (int)HttpStatusCode.BadRequest,
                        ResponseMessage = ResponseMessageConstants.VALIDATIONFAIL,

                    };
                    return new BadRequestObjectResult(result);
                };
           });

3

এখানে আপনি একে একে মডেল রাজ্যের ত্রুটি দেখানোর জন্য পরীক্ষা করতে পারেন

 public HttpResponseMessage CertificateUpload(employeeModel emp)
    {
        if (!ModelState.IsValid)
        {
            string errordetails = "";
            var errors = new List<string>();
            foreach (var state in ModelState)
            {
                foreach (var error in state.Value.Errors)
                {
                    string p = error.ErrorMessage;
                    errordetails = errordetails + error.ErrorMessage;

                }
            }
            Dictionary<string, object> dict = new Dictionary<string, object>();



            dict.Add("error", errordetails);
            return Request.CreateResponse(HttpStatusCode.BadRequest, dict);


        }
        else
        {
      //do something
        }
        }

}


3

সি শার্প

    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ModelState.IsValid == false)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(
                    HttpStatusCode.BadRequest, actionContext.ModelState);
            }
        }
    }

...

    [ValidateModel]
    public HttpResponseMessage Post([FromBody]AnyModel model)
    {

জাভাস্ক্রিপ্ট

$.ajax({
        type: "POST",
        url: "/api/xxxxx",
        async: 'false',
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),
        error: function (xhr, status, err) {
            if (xhr.status == 400) {
                DisplayModelStateErrors(xhr.responseJSON.ModelState);
            }
        },
....


function DisplayModelStateErrors(modelState) {
    var message = "";
    var propStrings = Object.keys(modelState);

    $.each(propStrings, function (i, propString) {
        var propErrors = modelState[propString];
        $.each(propErrors, function (j, propError) {
            message += propError;
        });
        message += "\n";
    });

    alert(message);
};

2

আমার গ্রহণযোগ্য সমাধানের প্যাটার্নটি কার্যকর করার ক্ষেত্রে আমার একটি সমস্যা ছিল যেখানে নির্দিষ্ট মডেল সামগ্রীর জন্য আমার ModelStateFilterসর্বদা false(এবং পরবর্তীকালে একটি 400) ফিরে আসত actionContext.ModelState.IsValid:

public class ModelStateFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            actionContext.Response = new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest};
        }
    }
}

আমি কেবল জেএসএনকেই গ্রহণ করি, তাই আমি একটি কাস্টম মডেল বাইন্ডার শ্রেণি প্রয়োগ করেছি:

public class AddressModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
    {
        var posted = actionContext.Request.Content.ReadAsStringAsync().Result;
        AddressDTO address = JsonConvert.DeserializeObject<AddressDTO>(posted);
        if (address != null)
        {
            // moar val here
            bindingContext.Model = address;
            return true;
        }
        return false;
    }
}

যা আমি আমার মডেলের মাধ্যমে সরাসরি নিবন্ধভুক্ত করি

config.BindParameter(typeof(AddressDTO), new AddressModelBinder());

1

আপনি এখানে নথিভুক্ত হিসাবে ব্যতিক্রম ছুঁড়ে ফেলতে পারেন: http://blogs.msdn.com/b/youssefm/archive/2012/06/28/error-handling-in-asp-net-webapi.aspx

দ্রষ্টব্য, যে নিবন্ধটি পরামর্শ দেয় তা করার জন্য, System.Net.Http অন্তর্ভুক্ত করতে ভুলবেন না

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.