ডেটা প্রবেশের পরে স্ট্রিমগুলি ছাঁটাই করার সর্বোত্তম উপায় way আমি কি একটি কাস্টম মডেল বাইন্ডার তৈরি করব?


172

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

আমি সম্ভবত একটি কাস্টম মডেল বাইন্ডার তৈরি এবং সেখানে যে কোনও স্ট্রিংয়ের মান ট্রিমিংয়ের কথা ভেবেছিলাম ... এইভাবে, আমার সমস্ত ট্রিমিং লজিক এক জায়গায় রয়েছে। এই একটি ভাল পন্থা? এমন কোনও কোড নমুনা রয়েছে যা এটি করে?

উত্তর:


214
  public class TrimModelBinder : DefaultModelBinder
  {
    protected override void SetProperty(ControllerContext controllerContext, 
      ModelBindingContext bindingContext, 
      System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
      if (propertyDescriptor.PropertyType == typeof(string))
      {
        var stringValue = (string)value;
        if (!string.IsNullOrWhiteSpace(stringValue))
        {
          value = stringValue.Trim();
        }
        else
        {
          value = null;
        }
      }

      base.SetProperty(controllerContext, bindingContext, 
                          propertyDescriptor, value);
    }
  }

কিভাবে এই কোড সম্পর্কে?

ModelBinders.Binders.DefaultBinder = new TrimModelBinder();

Global.asax অ্যাপ্লিকেশন_স্টার্ট ইভেন্ট সেট করুন।


3
আমি কেবল ব্রেভিটির জন্য অভ্যন্তরীণ সর্বাধিক in the সহ কোডটি প্রতিস্থাপন করব: স্ট্রিং স্ট্রিংভ্যালু = (স্ট্রিং) মান; মান = স্ট্রিং।ইসনলআরএম্পটি (স্ট্রিংভ্যালু)? স্ট্রিংভ্যালু: স্ট্রিংভ্যালু.ট্রিম ();
সাইমন_উইভার

4
এটি আরও উন্নয়নের দাবিদার। আমি সত্যি অবাক হয়েছি এমভিসি দলটি এটি ডিফল্ট মডেল বাইন্ডারে প্রয়োগ করতে বেছে নেয় নি ...
পোর্টম্যান

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

3
আমার মতো কারও জন্য ডিফল্ট মডেলবাইন্ডারে অস্পষ্টতা পাওয়া যায়, সঠিকটি সিস্টেম.ডাব্লব.এমভিসি ব্যবহার করছে।
জেফএম

3
type="password"ইনপুটগুলি ছোঁয়াতে রেখে কীভাবে আপনি এটি পরিবর্তন করবেন ?
এক্সট্রাগোরি

77

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

ModelBinders.Binders.Add(typeof(string),new TrimModelBinder());

শ্রেণী:

public class TrimModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext,
    ModelBindingContext bindingContext)
    {
        ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueResult== null || valueResult.AttemptedValue==null)
           return null;
        else if (valueResult.AttemptedValue == string.Empty)
           return string.Empty;
        return valueResult.AttemptedValue.Trim();
    }
}

@haacked পোস্টে উপর ভিত্তি করে: http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx


1
পরিষ্কার সমাধানের জন্য +1! আপনি returnবিবৃতিগুলির ক্রম পরিবর্তন করে এবং শর্তটিকে উপেক্ষা করে আপনার কোডের পঠনযোগ্যতা আরও উন্নত করতে পারেন :if (valueResult == null || string.IsNullOrEmpty(valueResult.AttemptedValue)) return null;
মারিয়াস শুলজ

6
এটি [ValidateInput (মিথ্যা)] নিয়ামক বৈশিষ্ট্যটি পরিচালনা করে না। এটি "বিপজ্জনক অনুরোধ ..." ব্যতিক্রম ঘটায়।
কোডগ্রু

2
যারা 'বিপজ্জনক অনুরোধ ...' ব্যতিক্রম পাচ্ছেন, তাদের এই নিবন্ধটি দেখুন - ব্লগস.টিগা.এনএল
martijn/

2
আমার একজন সহকর্মী এর বিভিন্নতা বাস্তবায়িত করেছেন যা সমস্ত ধরণের সমস্যার কারণ হয়ে দাঁড়িয়েছে : Issue.umbraco.org/issue/U4-6665 আমি সর্বদা একে অপরের চেয়ে বেশি পছন্দ করার পরিবর্তে নাল এবং ফাঁকা ফিরে আসার পরামর্শ দিই (আপনার ক্ষেত্রে, আপনি মানটি খালি স্ট্রিং হয়ে গেলেও সর্বদা নালায় ফিরে আসে)।
নিকোলাস ওয়েস্টবি

2
এটি [AllowHtml]মডেল বৈশিষ্ট্যগুলিতে বৈশিষ্ট্যটি ভঙ্গ করে বলে মনে হচ্ছে ( [ValidateInput(false)]উপরে বর্ণিত কোডগ্রু হিসাবে
মিংগুই স্যামুয়েল

43

@ টেকপাড়ার উত্তরে একটি উন্নতি।

প্রকল্পে কিছুটা:

public class NoTrimAttribute : Attribute { }

ট্রিমমোডেলবাইন্ডারে শ্রেণি পরিবর্তন

if (propertyDescriptor.PropertyType == typeof(string))

প্রতি

if (propertyDescriptor.PropertyType == typeof(string) && !propertyDescriptor.Attributes.Cast<object>().Any(a => a.GetType() == typeof(NoTrimAttribute)))

এবং আপনি [NoTrim] অ্যাট্রিবিউট দিয়ে ছাঁটাই করা থেকে বাদ দেওয়ার জন্য বৈশিষ্ট্যগুলি চিহ্নিত করতে পারেন।


1
@ কোরাইমে আইমোডেলবাইন্ডার পদ্ধতির ব্যবহার করার সময় আমরা কীভাবে এই বৈশিষ্ট্যের মতো কিছু বাস্তবায়ন করতে পারি? কিছু অ্যাপ্লিকেশনগুলিতে আমি একটি আলাদা (তৃতীয় পক্ষের) মডেল বাইন্ডার ব্যবহার করি (যেমন, এস # আরপ আর্কিটিকচার)। আমি প্রকল্পগুলির মধ্যে ভাগ করা একটি ব্যক্তিগত ডিএলএল এ লিখতে চাই, সুতরাং এটির একটি ইমোডেলবাইন্ডার পদ্ধতির হওয়া দরকার।
কার্ল বুসেমা 19

1
@ কার্লবসেমা এখানে একটি ইমোডেলবাইন্ডার থেকে বৈশিষ্ট্য অ্যাক্সেস সম্পর্কে একটি প্রশ্ন রয়েছে about stackoverflow.com/questions/6205176
ম্যাক অ্যাটাক

4
আমি এটি একটি মহান ছাড়াও কিন্তু আমি প্রতিস্থাপন করবে .Cast<object>().Any(a => a.GetType() == typeof(NoTrimAttribute))সঙ্গে .OfType<NoTrimAttribute>().Any()। একটু ক্লিনার।
DBueno

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

17

সি # 6 এর উন্নতির সাথে সাথে আপনি এখন একটি খুব কমপ্যাক্ট মডেল বাইন্ডার লিখতে পারেন যা সমস্ত স্ট্রিং ইনপুটগুলি ছাঁটাই করবে:

public class TrimStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var attemptedValue = value?.AttemptedValue;

        return string.IsNullOrWhiteSpace(attemptedValue) ? attemptedValue : attemptedValue.Trim();
    }
}

বাঁধার সময় মডেল বাইন্ডারটি ব্যবহার করার জন্য Application_Start()আপনার Global.asax.csফাইলটিতে এই লাইনটি কোথাও অন্তর্ভুক্ত করতে হবে string:

ModelBinders.Binders.Add(typeof(string), new TrimStringModelBinder());

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

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

public class TrimStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && bindingContext.ModelMetadata.RequestValidationEnabled;
        var unvalidatedValueProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;

        var value = unvalidatedValueProvider == null ?
          bindingContext.ValueProvider.GetValue(bindingContext.ModelName) :
          unvalidatedValueProvider.GetValue(bindingContext.ModelName, !shouldPerformRequestValidation);

        var attemptedValue = value?.AttemptedValue;

        return string.IsNullOrWhiteSpace(attemptedValue) ? attemptedValue : attemptedValue.Trim();
    }
}

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

@ অ্যাড্রিয়ান, আইমোডেলবাইন্ডার ইন্টারফেসটিতে রিটার্ন টাইপের বুল সহ কেবলমাত্র বিনডমোডেল রয়েছে। তাহলে আপনি এখানে রিটার্ন টাইপ অবজেক্টের সাথে কীভাবে ব্যবহার করেছেন?
মাগেন্দ্রন ভি

@ ম্যাজেন্ড্রানভি আপনি কোন ইন্টারফেসটি দেখছেন তা আমি নিশ্চিত নই, তবে এই উত্তরটি এএসপি.নেট এমভিসি 5 এর ইমোডেলবাইন্ডারের উপর ভিত্তি করে তৈরি করা হয়েছে, যা কোনও বস্তুটি প্রত্যাবর্তন করবে: ডকস.মাইক্রোসফটকম
অ্যাড্রিয়ান

1
অ্যারোন হাডন আমি এড়িয়ে যাবার বৈধতা হ্যান্ডেল করার জন্য একটি উদাহরণ অন্তর্ভুক্ত করার জন্য আমার উত্তর আপডেট করেছি
অ্যাড্রিয়ান

যদি আপনার পাসওয়ার্ড ক্ষেত্রগুলিতে সঠিক ডেটাটাইপ সেট থাকে (যেমন [ডাটাটাইপ (ডেটাটাইপ। পাসওয়ার্ড)]) থাকে তবে আপনি নিম্নলিখিত লাইনটি নিম্নরূপে আপডেট করতে পারেন যাতে এটি এই ক্ষেত্রগুলিকে ছাঁটাই না করে: রিটার্ন স্ট্রিং। বাইন্ডিং কনটেক্সট.মোডেলমেটাটাটা.ডাটাটাইপনেম == "পাসওয়ার্ড"? প্রয়াসভ্যালু: প্রচেষ্টা ভ্যালু.ট্রিম ();
ট্রাফলেট

15

ইন ASP.Net কোর 2 এই আমার জন্য কাজ করেন। আমি [FromBody]আমার কন্ট্রোলার এবং জেএসএন ইনপুটটিতে অ্যাট্রিবিউটটি ব্যবহার করছি । JSON deserialization এ স্ট্রিং হ্যান্ডলিংকে ওভাররাইড করতে আমি নিজের জেসন কনভার্টারটি নিবন্ধিত করেছি:

services.AddMvcCore()
    .AddJsonOptions(options =>
        {
            options.SerializerSettings.Converters.Insert(0, new TrimmingStringConverter());
        })

এবং এটি রূপান্তরকারী:

public class TrimmingStringConverter : JsonConverter
{
    public override bool CanRead => true;
    public override bool CanWrite => false;

    public override bool CanConvert(Type objectType) => objectType == typeof(string);

    public override object ReadJson(JsonReader reader, Type objectType,
        object existingValue, JsonSerializer serializer)
    {
        if (reader.Value is string value)
        {
            return value.Trim();
        }

        return reader.Value;
    }

    public override void WriteJson(JsonWriter writer, object value,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

আপনার সমাধান ভাল কাজ করে! ধন্যবাদ। IododBenderProvider ব্যবহার করে নেট কোর জন্য অন্যের সমাধানগুলি চেষ্টা করেছিলাম, এটি কার্যকর হয়নি।
সিড্রিক আর্নল্ড

স্টার্টআপ। ব্যতীত, এটি মডেলটিতে [জসনকনভার্টর (টাইপফ (ট্রিমিংস্ট্রিংকভার্টার)) হিসাবেও ব্যবহার করা যেতে পারে। BTW। ব্যবহারের পিছনে কোনও কারণ আছে? পরিবর্তে () সন্নিবেশ করুন। (যোগ করুন)?
ছিলে

@ পূর্বের আমি অনুমান করি যে আমি সবেমাত্র করেছি। অন্য রূপান্তরকারীদের আগে এটি চালিত হয় তা নিশ্চিত করার জন্য () যুক্ত করুন) এখন মনে পড়ছে না।
কাই জি

ডিফল্টকন্ট্র্যাক্ট রিসোলভারের ওভারহেডের পারফরম্যান্স কী?
মৌলিক মোদি

13

@ টেকপাড়ার উত্তরের আর একটি বৈকল্পিক তবে একটি ভিন্ন টুইস্ট সহ:

1) আমি "স্ট্রিংট্রিম" অ্যাট্রিবিউট মেকানিজমটিকে পছন্দ করি (@ অ্যান্টনের "নট ট্রাইম" উদাহরণের তুলনায়)।

২) মডেলস্টেটটি সঠিকভাবে জনবহুল এবং ডিফল্ট বৈধতা / গ্রহণ / প্রত্যাখ্যান প্যাটার্নটি সাধারণ হিসাবে ব্যবহার করা যেতে পারে, অর্থাৎ ট্রুডউপেটমোডেল (মডেল) প্রয়োগ করার জন্য এবং মডেলস্টেট.ক্লায়ার () সমস্ত পরিবর্তন স্বীকার করার জন্য সেটমোডেলভ্যালুতে একটি অতিরিক্ত কল প্রয়োজন।

এটিকে আপনার সত্তা / ভাগ করা লাইব্রেরিতে রাখুন:

/// <summary>
/// Denotes a data field that should be trimmed during binding, removing any spaces.
/// </summary>
/// <remarks>
/// <para>
/// Support for trimming is implmented in the model binder, as currently
/// Data Annotations provides no mechanism to coerce the value.
/// </para>
/// <para>
/// This attribute does not imply that empty strings should be converted to null.
/// When that is required you must additionally use the <see cref="System.ComponentModel.DataAnnotations.DisplayFormatAttribute.ConvertEmptyStringToNull"/>
/// option to control what happens to empty strings.
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class StringTrimAttribute : Attribute
{
}

তারপরে এটি আপনার এমভিসি অ্যাপ্লিকেশন / লাইব্রেরিতে রয়েছে:

/// <summary>
/// MVC model binder which trims string values decorated with the <see cref="StringTrimAttribute"/>.
/// </summary>
public class StringTrimModelBinder : IModelBinder
{
    /// <summary>
    /// Binds the model, applying trimming when required.
    /// </summary>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Get binding value (return null when not present)
        var propertyName = bindingContext.ModelName;
        var originalValueResult = bindingContext.ValueProvider.GetValue(propertyName);
        if (originalValueResult == null)
            return null;
        var boundValue = originalValueResult.AttemptedValue;

        // Trim when required
        if (!String.IsNullOrEmpty(boundValue))
        {
            // Check for trim attribute
            if (bindingContext.ModelMetadata.ContainerType != null)
            {
                var property = bindingContext.ModelMetadata.ContainerType.GetProperties()
                    .FirstOrDefault(propertyInfo => propertyInfo.Name == bindingContext.ModelMetadata.PropertyName);
                if (property != null && property.GetCustomAttributes(true)
                    .OfType<StringTrimAttribute>().Any())
                {
                    // Trim when attribute set
                    boundValue = boundValue.Trim();
                }
            }
        }

        // Register updated "attempted" value with the model state
        bindingContext.ModelState.SetModelValue(propertyName, new ValueProviderResult(
            originalValueResult.RawValue, boundValue, originalValueResult.Culture));

        // Return bound value
        return boundValue;
    }
}

আপনি যদি বাইন্ডারে সম্পত্তি মান সেট না করেন, এমনকি আপনি যখন কোনও কিছু পরিবর্তন করতে চান না, আপনি সেই সম্পত্তি পুরোপুরি মডেলস্টেট থেকে অবরুদ্ধ করে দেবেন! এটি কারণ আপনি সমস্ত স্ট্রিং ধরণের বাঁধাই হিসাবে নিবন্ধিত হয়েছেন, সুতরাং এটি প্রদর্শিত হবে (আমার পরীক্ষায়) যে ডিফল্ট বাইন্ডার তখন আপনার জন্য এটি করবে না।


7

এএসপি.নেট কোর 1.0 এ কীভাবে এটি করতে হয় তার জন্য অতিরিক্ত তথ্য। যুক্তি বেশ পরিবর্তন হয়েছে।

এটি কীভাবে করা যায় সে সম্পর্কে আমি একটি ব্লগ পোস্ট লিখেছিলাম , এটি কিছুটা বিশদভাবে ব্যাখ্যা করে

সুতরাং ASP.NET কোর 1.0 সমাধান:

প্রকৃত ছাঁটাই করতে মডেল বাইন্ডার

public class TrimmingModelBinder : ComplexTypeModelBinder  
{
    public TrimmingModelBinder(IDictionary propertyBinders) : base(propertyBinders)
    {
    }

    protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
    {
        if(result.Model is string)
        {
            string resultStr = (result.Model as string).Trim();
            result = ModelBindingResult.Success(resultStr);
        }

        base.SetProperty(bindingContext, modelName, propertyMetadata, result);
    }
}

সর্বশেষতম সংস্করণে আপনারও মডেল বাইন্ডার সরবরাহকারী প্রয়োজন, এটি আপনাকে জানায় যে এই মডেলটির জন্য এই বাইন্ডারটি ব্যবহার করা উচিত

public class TrimmingModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
        {
            var propertyBinders = new Dictionary();
            foreach (var property in context.Metadata.Properties)
            {
                propertyBinders.Add(property, context.CreateBinder(property));
            }

            return new TrimmingModelBinder(propertyBinders);
        }

        return null;
    }
}

তারপরে এটি স্টার্টআপ.সিগুলিতে নিবন্ধিত হতে হবে

 services.AddMvc().AddMvcOptions(options => {  
       options.ModelBinderProviders.Insert(0, new TrimmingModelBinderProvider());
 });

এটি আমার পক্ষেও কার্যকর হয়নি, আমার সমস্ত ক্ষেত্র এখন শূন্য
সিড্রিক আর্নল্ড

5

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

    $('form').submit(function () {
        $(this).find('input:text').each(function () {
            $(this).val($.trim($(this).val()));
        })
    });

1
2 টি জিনিস: 1 - আপনার ক্লায়েন্টের অবজেক্টগুলিকে ক্যাশে করুন (যেমন $ (এটি)), 2 - আপনি কখনই ক্লায়েন্ট ইনপুটগুলিতে নির্ভর করতে পারবেন না তবে আপনি অবশ্যই সার্ভার কোডের উপর নির্ভর করতে পারবেন। সুতরাং আপনার উত্তরটি সার্ভার কোডের উত্তরগুলির সমাপ্তি :)
গ্রুমানোজ

5

এমভিসি কোর ক্ষেত্রে

দপ্তরী:

using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.Threading.Tasks;
public class TrimmingModelBinder
    : IModelBinder
{
    private readonly IModelBinder FallbackBinder;

    public TrimmingModelBinder(IModelBinder fallbackBinder)
    {
        FallbackBinder = fallbackBinder ?? throw new ArgumentNullException(nameof(fallbackBinder));
    }

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (valueProviderResult != null &&
            valueProviderResult.FirstValue is string str &&
            !string.IsNullOrEmpty(str))
        {
            bindingContext.Result = ModelBindingResult.Success(str.Trim());
            return Task.CompletedTask;
        }

        return FallbackBinder.BindModelAsync(bindingContext);
    }
}

প্রদানকারী:

using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using System;

public class TrimmingModelBinderProvider
    : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (!context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(string))
        {
            return new TrimmingModelBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));
        }

        return null;
    }
}

নিবন্ধকরণ কার্য:

    public static void AddStringTrimmingProvider(this MvcOptions option)
    {
        var binderToFind = option.ModelBinderProviders
            .FirstOrDefault(x => x.GetType() == typeof(SimpleTypeModelBinderProvider));

        if (binderToFind == null)
        {
            return;
        }

        var index = option.ModelBinderProviders.IndexOf(binderToFind);
        option.ModelBinderProviders.Insert(index, new TrimmingModelBinderProvider());
    }

নিবন্ধন:

service.AddMvc(option => option.AddStringTrimmingProvider())

+1 টি। ঠিক আমি খুঁজছেন ছিল কি. নিবন্ধকরণ কার্যক্রমে "বাইন্ডারটোফাইন্ড" কোডটির উদ্দেশ্য কী?
ব্র্যাড

আমি ঠিক SimpleTypeModelBinderProviderএকই সূচি বজায় রেখে কাস্টম সরবরাহকারীকে ফালব্যাক দিয়ে রাখার চেষ্টা করছি ।
বিকাশ কুমার

পুরো বিবরণটি এখানে পাওয়া যাবে vikutech.blogspot.in/2018/02/…
বিকাশ কুমার

3

পার্টিতে দেরীতে, তবে এমভিসি 5.2.3 এর জন্য প্রয়োজনীয় সংযোজনের সংক্ষিপ্তসার নীচে আপনি যদি skipValidationবিল্ড-ইন মান সরবরাহকারীর প্রয়োজনীয়তা পরিচালনা করতে চান তবে।

public class TrimStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // First check if request validation is required
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && 
            bindingContext.ModelMetadata.RequestValidationEnabled;

        // determine if the value provider is IUnvalidatedValueProvider, if it is, pass in the 
        // flag to perform request validation (e.g. [AllowHtml] is set on the property)
        var unvalidatedProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;

        var valueProviderResult = unvalidatedProvider?.GetValue(bindingContext.ModelName, !shouldPerformRequestValidation) ??
            bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        return valueProviderResult?.AttemptedValue?.Trim();
    }
}

Global.asax

    protected void Application_Start()
    {
        ...
        ModelBinders.Binders.Add(typeof(string), new TrimStringModelBinder());
        ...
    }

2

আমি সমাধানের সাথে একমত নই। আপনার getPropertyValue ওভাররাইড করা উচিত কারণ সেটপ্রপার্টির ডেটাও মডেলস্টেট দ্বারা পূরণ করা যেতে পারে। ইনপুট উপাদানগুলি থেকে কাঁচা তথ্য ধরতে এটি লিখুন:

 public class CustomModelBinder : System.Web.Mvc.DefaultModelBinder
{
    protected override object GetPropertyValue(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, System.Web.Mvc.IModelBinder propertyBinder)
    {
        object value = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);

        string retval = value as string;

        return string.IsNullOrWhiteSpace(retval)
                   ? value
                   : retval.Trim();
    }

}

বৈশিষ্ট্য দ্বারা ফিল্টার করুন ডেস্ক্রিপ্ট প্রপার্টি টাইপ আপনি যদি কেবল স্ট্রিংয়ের মানগুলিতেই আগ্রহী হন তবে এটি বিবেচ্য নয় কারণ যা কিছু আসে তা মূলত একটি স্ট্রিং।


2

জন্য ASP.NET কোর , প্রতিস্থাপন ComplexTypeModelBinderProviderএকটি প্রদানকারী যে স্ট্রিং ট্রিম সঙ্গে।

আপনার স্টার্টআপ কোড ConfigureServicesপদ্ধতিতে এটি যুক্ত করুন:

services.AddMvc()
    .AddMvcOptions(s => {
        s.ModelBinderProviders[s.ModelBinderProviders.TakeWhile(p => !(p is ComplexTypeModelBinderProvider)).Count()] = new TrimmingModelBinderProvider();
    })

এটির TrimmingModelBinderProviderমতো সংজ্ঞা দিন :

/// <summary>
/// Used in place of <see cref="ComplexTypeModelBinderProvider"/> to trim beginning and ending whitespace from user input.
/// </summary>
class TrimmingModelBinderProvider : IModelBinderProvider
{
    class TrimmingModelBinder : ComplexTypeModelBinder
    {
        public TrimmingModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders) { }

        protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
        {
            var value = result.Model as string;
            if (value != null)
                result = ModelBindingResult.Success(value.Trim());
            base.SetProperty(bindingContext, modelName, propertyMetadata, result);
        }
    }

    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType) {
            var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
            for (var i = 0; i < context.Metadata.Properties.Count; i++) {
                var property = context.Metadata.Properties[i];
                propertyBinders.Add(property, context.CreateBinder(property));
            }
            return new TrimmingModelBinder(propertyBinders);
        }
        return null;
    }
}

এর কুৎসিত অংশটি হ'ল GetBinderযুক্তিটির অনুলিপি এবং আটকানো ComplexTypeModelBinderProvider, তবে আপনাকে এড়াতে দেওয়ার কোনও হুক বলে মনে হচ্ছে না।


আমি জানি না কেন তবে এটিএসপি নেট নেট 1.1.1 এর জন্য কাজ করে না। আমি নিয়ামক ক্রিয়ায় মডেল অবজেক্টের সমস্ত বৈশিষ্ট্যগুলি বাতিল। "সেটপ্রোপার্টি" পদ্ধতিটিকে স্নায়ু বলা হয়।
ওয়াল্ডো

আমার জন্য কাজ করেনি, আমার সম্পত্তি শুরুতে স্থান এখনও আছে।
সিড্রিক আর্নল্ড

2

আমি ক্যোরি স্ট্রিং প্যারামিটার মানগুলি এবং ফর্মের মানগুলি ট্রিম করতে মান সরবরাহকারী তৈরি করেছি। এটি ASP.NET কোর 3 দিয়ে পরীক্ষা করা হয়েছিল এবং নিখুঁতভাবে কাজ করে।

public class TrimmedFormValueProvider
    : FormValueProvider
{
    public TrimmedFormValueProvider(IFormCollection values)
        : base(BindingSource.Form, values, CultureInfo.InvariantCulture)
    { }

    public override ValueProviderResult GetValue(string key)
    {
        ValueProviderResult baseResult = base.GetValue(key);
        string[] trimmedValues = baseResult.Values.Select(v => v?.Trim()).ToArray();
        return new ValueProviderResult(new StringValues(trimmedValues));
    }
}

public class TrimmedQueryStringValueProvider
    : QueryStringValueProvider
{
    public TrimmedQueryStringValueProvider(IQueryCollection values)
        : base(BindingSource.Query, values, CultureInfo.InvariantCulture)
    { }

    public override ValueProviderResult GetValue(string key)
    {
        ValueProviderResult baseResult = base.GetValue(key);
        string[] trimmedValues = baseResult.Values.Select(v => v?.Trim()).ToArray();
        return new ValueProviderResult(new StringValues(trimmedValues));
    }
}

public class TrimmedFormValueProviderFactory
    : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        if (context.ActionContext.HttpContext.Request.HasFormContentType)
            context.ValueProviders.Add(new TrimmedFormValueProvider(context.ActionContext.HttpContext.Request.Form));
        return Task.CompletedTask;
    }
}

public class TrimmedQueryStringValueProviderFactory
    : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        context.ValueProviders.Add(new TrimmedQueryStringValueProvider(context.ActionContext.HttpContext.Request.Query));
        return Task.CompletedTask;
    }
}

তারপরে ConfigureServices()স্টার্টআপ। সি-তে ফাংশনে মান প্রদানকারী কারখানার নিবন্ধন করুন

services.AddControllersWithViews(options =>
{
    int formValueProviderFactoryIndex = options.ValueProviderFactories.IndexOf(options.ValueProviderFactories.OfType<FormValueProviderFactory>().Single());
    options.ValueProviderFactories[formValueProviderFactoryIndex] = new TrimmedFormValueProviderFactory();

    int queryStringValueProviderFactoryIndex = options.ValueProviderFactories.IndexOf(options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>().Single());
    options.ValueProviderFactories[queryStringValueProviderFactoryIndex] = new TrimmedQueryStringValueProviderFactory();
});

0

অ্যাট্রিবিউট পদ্ধতির পরামর্শ দেওয়ার মতো অনেকগুলি পোস্ট রয়েছে। এখানে একটি প্যাকেজ ইতিমধ্যে একটি ট্রিম অ্যাট্রিবিউট এবং আরও অনেক কিছু আছে যা হল: Dado.ComponentModel.Mutations বা NuGet

public partial class ApplicationUser
{
    [Trim, ToLower]
    public virtual string UserName { get; set; }
}

// Then to preform mutation
var user = new ApplicationUser() {
    UserName = "   M@X_speed.01! "
}

new MutationContext<ApplicationUser>(user).Mutate();

মিউটেটে () কল করার পরে, ব্যবহারকারীর ব্যবহারকারী নামটি রূপান্তরিত হবে m@x_speed.01!

এই উদাহরণটি হোয়াইটস্পেসটি ছাঁটাই করবে এবং স্ট্রিংটিকে ছোট হাতের অক্ষরে পরিণত করবে। এটি বৈধতার পরিচয় দেয় না, তবে System.ComponentModel.Annotationsপাশাপাশি ব্যবহার করা যেতে পারে Dado.ComponentModel.Mutations


0

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

এখানে আমার কোড, প্রথমে একটি অ্যাকশন ফিল্টার তৈরি করুন:

public class TrimInputStringsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        foreach (var arg in context.ActionArguments)
        {
            if (arg.Value is string)
            {
                string val = arg.Value as string;
                if (!string.IsNullOrEmpty(val))
                {
                    context.ActionArguments[arg.Key] = val.Trim();
                }

                continue;
            }

            Type argType = arg.Value.GetType();
            if (!argType.IsClass)
            {
                continue;
            }

            TrimAllStringsInObject(arg.Value, argType);
        }
    }

    private void TrimAllStringsInObject(object arg, Type argType)
    {
        var stringProperties = argType.GetProperties()
                                      .Where(p => p.PropertyType == typeof(string));

        foreach (var stringProperty in stringProperties)
        {
            string currentValue = stringProperty.GetValue(arg, null) as string;
            if (!string.IsNullOrEmpty(currentValue))
            {
                stringProperty.SetValue(arg, currentValue.Trim(), null);
            }
        }
    }
}

এটি ব্যবহার করার জন্য, হয় বিশ্বব্যাপী ফিল্টার হিসাবে নিবন্ধন করুন বা আপনার ক্রিয়াসমূহ TrimIputputtrus গুণাবলী দিয়ে সজ্জিত করুন।

[TrimInputStrings]
public IActionResult Register(RegisterViewModel registerModel)
{
    // Some business logic...
    return Ok();
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.