天道酬勤,学无止境

数据输入后修剪字符串的最佳方法。 我应该创建自定义模型活页夹吗?(Best way to trim strings after data entry. Should I create a custom model binder?)

问题

我正在使用ASP.NET MVC,我希望在将所有用户输入的字符串字段插入数据库之前先对其进行修剪。 并且由于我有许多数据输入表单,因此我正在寻找一种修整所有字符串的方法,而不是显式修整每个用户提供的字符串值。 我很想知道人们如何以及何时修剪琴弦。

我考虑过可能要创建一个自定义模型联编程序并在那里修剪任何字符串值...那样,我所有的修剪逻辑都包含在一个地方。 这是一个好方法吗? 是否有任何代码示例可以做到这一点?

回答1
  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 Application_Start事件。

回答2

这是@takepara相同的分辨率,但与IModelBinder而不是DefaultModelBinder相同,因此可以通过以下方式在global.asax中添加modelbinder

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

回答3

@takepara答案的一项改进。

在项目中:

public class NoTrimAttribute : Attribute { }

在TrimModelBinder类中更改

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

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

并且您可以使用[NoTrim]属性标记要修剪的属性。

回答4

ASP.Net Core 2中,这对我有用。 我在控制器和JSON输入中使用[FromBody]属性。 为了覆盖JSON反序列化中的字符串处理,我注册了自己的JsonConverter:

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();
    }
}
回答5

通过C#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();
    }
}

您需要在Global.asax.cs文件的Application_Start()中的某处包括以下行,以便在绑定string s时使用模型绑定器:

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

我发现最好使用这样的模型绑定程序,而不是覆盖默认的模型绑定程序,因为这样,无论何时将其绑定为string ,无论将其直接用作方法参数还是作为模型类的属性,都将使用它。 但是,如果您按照此处的其他答案覆盖默认的模型绑定器,则在绑定模型上的属性时才有效,在将string作为操作方法的参数时则无效

编辑:评论者问有关不应该验证字段时的处理情况。 我最初的回答被简化为仅处理OP提出的问题,但是对于那些感兴趣的人,您可以使用以下扩展的模型绑定器来进行验证:

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();
    }
}
回答6

@takepara答案的另一个变体,但又有不同的转折:

1)我更喜欢选择加入的“ StringTrim”属性机制(而不是@Anton的选择退出的“ NoTrim”示例)。

2)需要额外调用SetModelValue以确保正确填充ModelState,并且可以正常使用默认的验证/接受/拒绝模式,即应用TryUpdateModel(model)和接受所有更改的ModelState.Clear()。

将其放在您的实体/共享库中:

/// <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
{
}

然后在您的MVC应用程序/库中:

/// <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;
    }
}

如果您没有在活页夹中设置属性值,即使您不想更改任何内容,也将完全阻止该属性进入ModelState! 这是因为您已注册为绑定所有字符串类型,所以(在我的测试中)默认绑定器似乎不会为您执行此操作。

回答7

为任何在ASP.NET Core 1.0中搜索如何执行此操作的人提供的额外信息。 逻辑发生了很大变化。

我写了一篇有关如何做的博客文章,它对事情进行了更详细的解释

因此,ASP.NET Core 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);
    }
}

另外,您还需要最新版本的Model Binder Provider,这表明该模型应使用此Binder

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;
    }
}

然后必须在Startup.cs中注册

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

如果是MVC Core

活页夹:

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())
回答9

在阅读了上面的出色答案和评论并变得越来越困惑的同时,我突然想到,嘿,我想知道是否有jQuery解决方案。 因此,对于像我一样感到有些困惑的其他人,我提供了以下jQuery代码段,这些代码段在提交表单之前对输入字段进行了修整。

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

我创建了值提供程序来修剪查询字符串参数值和表单值。 这已通过ASP.NET Core 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;
    }
}

然后在Startup.cs的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();
});
回答11

晚了,但是如果您要处理skipValidation值提供程序的skipValidation要求,则以下总结了MVC 5.2.3所需的调整。

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());
        ...
    }
回答12

我不同意该解决方案。 您应该覆盖GetPropertyValue,因为SetProperty的数据也可以由ModelState填充。 要从输入元素中捕获原始数据,请编写以下代码:

 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();
    }

}

如果您真的只对字符串值感兴趣,请按propertyDescriptor PropertyType进行过滤,但不要紧,因为其中的所有内容基本上都是字符串。

回答13

对于ASP.NET Core ,用修剪字符串的提供程序替换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;
    }
}

丑陋的部分是从ComplexTypeModelBinderProvider复制和粘贴GetBinder逻辑,但是似乎没有任何挂钩可以避免这种情况。

回答14

有很多帖子建议使用属性方法。 这是一个已经具有trim属性和许多其他属性的程序包: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();

调用Mutate()之后,user.UserName将被更改为m@x_speed.01!

本示例将修剪空格并将字符串大小写为小写。 它没有引入验证,但是System.ComponentModel.Annotations可以与Dado.ComponentModel.Mutations一起Dado.ComponentModel.Mutations

回答15

我将其发布在另一个线程中。 在asp.net核心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);
            }
        }
    }
}

要使用它,请注册为全局过滤器,或使用TrimInputStrings属性装饰您的操作。

[TrimInputStrings]
public IActionResult Register(RegisterViewModel registerModel)
{
    // Some business logic...
    return Ok();
}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • MVC / MVVM /分层中的ViewModels-最佳做法?(ViewModels in MVC / MVVM / Separation of layers- best practices?)
    问题 我对使用ViewModels还是很陌生,我想知道,是否可以让ViewModel包含域模型的实例作为属性,或者这些域模型的属性应该是ViewModel本身的属性? 例如,如果我有一个类Album.cs public class Album { public int AlbumId { get; set; } public string Title { get; set; } public string Price { get; set; } public virtual Genre Genre { get; set; } public virtual Artist Artist { get; set; } } 您通常是让ViewModel持有Album.cs类的实例,还是让ViewModel拥有每个Album.cs类的属性的属性。 public class AlbumViewModel { public Album Album { get; set; } public IEnumerable<SelectListItem> Genres { get; set; } public IEnumerable<SelectListItem> Artists { get; set; } public int Rating { get; set; } // other properties
  • 我可以通过使用单引号转义单引号和周围的用户输入来防止SQL注入吗?(Can I protect against SQL injection by escaping single-quote and surrounding user input with single-quotes?)
    问题 我意识到在构建包含用户输入的查询时,参数化SQL查询是清理用户输入的最佳方法,但是我想知道使用用户输入并转义任何单引号并将整个字符串都用单引号引起来是怎么回事。 这是代码: sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'" 用户输入的任何单引号都将替换为双单引号,这消除了用户结束字符串的能力,因此他们可能键入的其他任何内容(例如分号,百分号等)都将成为字符串的一部分,并且实际上并未作为命令的一部分执行。 我们使用的是Microsoft SQL Server 2000,我相信单引号是唯一的字符串定界符,也是避免字符串定界符的唯一方法,因此无法执行用户键入的任何内容。 我看不到有什么方法可以发起针对此的SQL注入攻击,但是我意识到,如果这在我看来像防弹一样,那么其他人可能已经想到了,并且这将是普遍的做法。 此代码有什么问题? 有没有办法使SQL注入攻击超越这种清理技术? 利用此技术的样本用户输入将非常有帮助。 更新: 我仍然不知道有什么方法可以有效地对此代码发起SQL注入攻击。 一些人建议反斜杠可以转义一个单引号,而让另一个反斜杠结束该字符串,以便该字符串的其余部分将作为SQL命令的一部分执行,并且我意识到该方法可以将SQL注入到一个MySQL数据库,但是在SQL Server 2000中
  • GPT-2和Transformer很好用,但不是AI生成文本的最终目标
    019 年 2 月,OpenAI 发表了一篇 论文,描述了基于 AI 的文本生成模型 GPT-2,该模型基于 Transformer 架构,针对互联网大量的文本上进行训练。从文本生成的角度来看,所包含的演示是令人印象深刻的:在很长的时间范围内,文本是连贯的,语法和标点符号近乎完美。与此同时,其允许任何人下载模型(考虑到完整的模型可以被滥用于大规模地生成假新闻,这里给的是较小的版本)的 Python 代码和加载下载的模型并生成预测的 TensorFlow 代码已经 在 GitHub 上开源了。Neil Shepperd 创建了一个 OpenAI 仓库的 派生,该存储库包含额外的代码,允许在自定义数据集上微调现有的 OpenAI 模型。不久之后创建了一个笔记本,该 笔记本 可以复制到 Google Colaboratory,并把 Shepperd 的仓库克隆到微调的 GPT-2,该 GPT-2 由一个免费的 GPU 支持。从那时起,GPT-2 生成文本开始扩散:Gwern Branwen 等研究人员制作了 GPT-2 Poetry,而 Janelle Shane 制作了 GPT-2 Dungeons 和 Dragons 人物简介。我等着想看看是否有人会制作一个工具来帮助精简这个微调和文本生成工作流,像我已经为基于递归神经网络的文本生成所做的 textgenrnn。几个月后,还没有人做
  • 在输入中对ng-model进行过滤(filters on ng-model in an input)
    问题 我有一个文本输入,并且我不想允许用户使用空格,并且键入的所有内容都将变为小写。 我知道我不允许在ng-model上使用过滤器。 ng-model='tags | lowercase | no_spaces' 我看着创建自己的指令,但是向$parsers和$formatters添加函数并没有更新输入,只有其他ng-model元素才更新。 如何更改当前输入的输入内容? 我实质上是在尝试创建“标签”功能,该功能与StackOverflow上的功能相同。 回答1 我建议您观察模型值并在发生变化时对其进行更新:http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p=preview 唯一有趣的问题是空格:在AngularJS 1.0.3中,输入的ng-model会自动修剪字符串,因此,如果在结尾或开头添加空格,它不会检测到模型已更改(因此,空格不会被我自动删除)代码)。 但是在1.1.1中,有一个“ ng-trim”指令允许禁用此功能(提交)。 因此,我决定使用1.1.1来实现您在问题中描述的确切功能。 回答2 我相信AngularJS输入和ngModel定向的意图是,无效输入永远不会在模型中结束。 该模型应始终有效。 拥有无效模型的问题在于,我们可能会让观察者根据无效模型触发并采取(不适当的)动作。 如我所见,这里的正确解决方案是插入$parsers管道
  • 为什么不从列表继承 ?(Why not inherit from List<T>?)
    问题 在计划程序时,我通常会像这样思考: 足球队只是足球运动员的名单。 因此,我应该用以下方式代表它: var football_team = new List<FootballPlayer>(); 该列表的顺序表示在名单中列出球员的顺序。 但是后来我意识到,除了球员名单外,球队还有其他属性,必须记录下来。 例如,本赛季的总成绩,当前预算,制服颜色,代表球队名称的string等。 所以我想: 好的,足球队就像一个球员名单,但是另外,它还有一个名字( string )和总得分(一个int )。 .NET没有提供用于存储足球队的课程,因此我将创建自己的课程。 最相似和相关的现有结构是List<FootballPlayer> ,所以我将从它继承: class FootballTeam : List<FootballPlayer> { public string TeamName; public int RunningTotal } 但是事实证明,有一条准则表明您不应该从List <T>继承。 我对该指南在两个方面完全感到困惑。 为什么不? 显然,List在某种程度上针对性能进行了优化。 怎么会这样? 如果我扩展List会导致什么性能问题? 到底会破裂什么? 我看到的另一个原因是List是由Microsoft提供的,并且我无法控制它,因此在公开“公共API”之后,以后将无法对其进行更改。
  • 在某些情况下禁用“必需的验证”属性(Disable Required validation attribute under certain circumstances)
    问题 我想知道是否可以在某些控制器操作中禁用“必需的验证”属性。 我想知道这是因为在我的一种编辑表单上,我不需要用户为他们先前已经指定的字段输入值。 但是,我然后实现了一种逻辑,即当他们输入值时,它会使用一些特殊的逻辑来更新模型,例如对值进行哈希处理等。 关于如何解决此问题有任何建议吗? 编辑: 是的,这里的客户验证是一个问题,因为它将不允许他们在不输入值的情况下提交表单。 回答1 通过使用视图模型可以轻松解决此问题。 视图模型是专门为给定视图的需求量身定制的类。 因此,例如,在您的情况下,您可以具有以下视图模型: public UpdateViewView { [Required] public string Id { get; set; } ... some other properties } public class InsertViewModel { public string Id { get; set; } ... some other properties } 将在其相应的控制器操作中使用: [HttpPost] public ActionResult Update(UpdateViewView model) { ... } [HttpPost] public ActionResult Insert(InsertViewModel model) { ... }
  • Android上的MVC模式(MVC pattern on Android)
    问题 是否可以在Android版Java中实现模型-视图-控制器模式? 还是已经通过活动实施了? 还是有更好的方法来为Android实现MVC模式? 回答1 在Android中,您没有MVC,但是您具有以下条件: 您可以通过分辨率,硬件等在各种XML文件中定义用户界面。 您可以通过语言环境等在各种XML文件中定义资源。 您可以扩展诸如ListActivity,TabActivity之类的类,并通过充气机来使用XML文件。 您可以根据需要为业务逻辑创建任意多个类。 已经为您编写了许多实用程序-DatabaseUtils,Html。 回答2 没有普遍唯一的MVC模式。 MVC是一个概念,而不是一个可靠的编程框架。 您可以在任何平台上实现自己的MVC。 只要您坚持以下基本思想,就可以实现MVC: 模型:要渲染的内容视图:如何渲染控制器:事件,用户输入 也可以这样考虑:在对模型进行编程时,模型不必担心渲染(或特定于平台的代码)。 该模型将对视图说,我不在乎您的渲染是Android还是iOS或Windows Phone,这就是我需要渲染的东西。 该视图将仅处理特定于平台的呈现代码。 当您使用Mono共享模型以开发跨平台应用程序时,这特别有用。 回答3 Android上的动作,视图和活动是使用Android UI的固有方法,并且是model-view-viewmodel(MVVM)模式的实现
  • 安全运营中心专业笔记
    转载了别人,初步看来下,应该是机翻的,看起来有些难懂,但是可以初步了解下。转载的地址:https://www.jianshu.com/p/f7d9b9f8fc4c 一、SOC 定义 安全运营中心(SOC)对不同的人有不同的含义。有些人说他们“运行安全平台”,别人说“他们处理事件”,还有人说“他们监控网络的安全”。BTHb:SOCTH中SOC的定义为: 一个集中在单一组织中的团队,负责监控信息技术环境中的漏洞、未经授权的活动、可接受的使用/策略/程序违规、网络入.侵和向网络外入.侵,并为网络事件响应过程提供直接支持。 简而言之,SOC是第一道防线。这个定义包含了成功SOC的几个重要策略。首先,SOC必须处于单一的管理和报告结构下,这样它就有了清晰的权限、资金、报告和责任。其次,SOC必须了解业务和IT环境的所有方面,从最小的工作站到云中的最大超级集群。第三,SOC需要了解其运营领域(AO)、它们将如何支持业务、监视业务应用程序和基础设施。这些标准必须包括在SOC宪章中。第四,SOC预算需要足够大,以持续投资于人员和支持交叉培训,而不是超级复杂的软件。这一概念引出了第五个策略:训练并鼓励分析师保持冷静,正确解读警报及其支持数据。这要求SOC分析人员受过良好的培训。 有一点值得详细说明。SOC团队可以通过几种不同的方法来建立它的AO。SOC可以使用IT通用控制程序、公司政策/程序
  • 什么是数据传输对象(DTO)?(What is a Data Transfer Object (DTO)?)
    问题 什么是数据传输对象? 在MVC中,模型类是DTO,如果不是,则有什么区别,我们是否需要两者? 回答1 数据传输对象是用于封装数据并将其从应用程序的一个子系统发送到另一个子系统的对象。 NTO应用程序中的服务层最常使用DTO在自身和UI层之间传输数据。 这样做的主要好处是,它减少了分布式应用程序中需要通过网络发送的数据量。 他们还在MVC模式中建立了出色的模型。 DTO的另一个用途是封装方法调用的参数。 如果某个方法采用的参数超过4个或5个,则这将很有用。 使用DTO模式时,您还将使用DTO汇编程序。 汇编程序用于从域对象创建DTO,反之亦然。 从域对象到DTO的转换,再转换回来,可能是一个代价高昂的过程。 如果您不创建分布式应用程序,那么您可能不会从该模式中看到任何巨大的好处,正如Martin Fowler在此处解释的那样 回答2 DTO的定义可以在Martin Fowler的网站上找到。 DTO用于将参数传递给方法并作为返回类型。 很多人在UI中使用它们,但其他人则从其中膨胀域对象。 回答3 DTO是一个愚蠢的对象-它仅包含属性并具有getter和setter,但没有其他任何有意义的逻辑(可能是compare()或equals()实现)。 通常,MVC中的模型类(此处假定为.net MVC)是DTO或DTO的集合/集合。 回答4 通常,值对象应该是不可变的。
  • GitHub Actions的机器学习推理上线,推进测试部署高度自动化
    GitHub Actions 是一个用于构建、测试和部署的自动化工具。举个例子快速了解下它是什么:每次你创建一个 Pull Request(带有某个标签)时,都会触发新的应用程序构建,然后它可以向高级开发人员发送消息,让他们快速查看代码。项目地址:https://github.com/gaborvecsei/Machine-Learning-Inference-With-GitHub-Actions我们将创建什么?在存储库上创建一个自定义操作和自动化工作流,你可以在其中使用经过训练的模型,并在某个问题有了新评论时触发它。你还可以找到模型训练和推理代码。我想要超级硬核,所以我选择了 Iris 数据集和随机森林分类器。这个树集成模型经过训练,可以根据萼片和花瓣的长度和宽度来识别花朵。这个模型的训练是在 Jupyter Notebook 上完成的。这些代码训练并序列化我们将用于预测的模型。当问题收到评论时,GitHub Actions 工作流将被触发。如果评论包含前缀 /predict,那么我们就开始解析评论,然后我们做一个预测并构造一个回复。最后一步,该消息由机器人在相同的问题下发回给用户。为了把事情做得更好,整个自定义操作将在 Docker 容器中运行。我们将找出工作流中的步骤,并为某些步骤创建单独的操作。一个工作流可以包含多个操作,但是在这个项目中,我们将使用单个操作
  • 百分点技术干货分享,万字长文深度解读机器翻译
    编者按在“机器翻译是如何炼成的(上)”的文章中,我们回顾了机器翻译的发展史。在本篇文章中,我们将分享机器翻译系统的理论算法和技术实践,讲解神经机器翻译具体是如何炼成的。读完本文,您将了解:神经机器翻译模型如何进化并发展成令NLP研究者万众瞩目的Transformer模型;基于Transformer模型,我们如何打造工业级的神经机器翻译系统。2013年~2014年不温不火的自然语言处理(NLP)领域发生了翻天覆地的变化,因为谷歌大脑的Mikolov等人提出了大规模的词嵌入技术word2vec,RNN、CNN等深度网络也开始应用于NLP的各项任务,全世界NLP研究者欢欣鼓舞、跃跃欲试,准备告别令人煎熬的平淡期,开启一个属于NLP的新时代。在这两年机器翻译领域同样发生了“The Big Bang”。2013年牛津大学Nal Kalchbrenner和Phil Blunsom提出端到端神经机器翻译(Encoder-Decoder模型),2014年谷歌公司的Ilya Sutskerver等人将LSTM引入到Encoder-Decoder模型中。这两件事标志着以神经网络作为基础的机器翻译,开始全面超越此前以统计模型为基础的统计机器翻译(SMT),并快速成为在线翻译系统的主流标配。2016年谷歌部署神经机器翻译系统(GNMT)之后,当时网上有一句广为流传的话:“作为一个翻译,看到这个新闻的时候
  • 修剪std :: string的最佳方法是什么?(What's the best way to trim std::string?)
    问题 我目前正在使用以下代码对程序中的所有std::strings进行右修剪: std::string s; s.erase(s.find_last_not_of(" \n\r\t")+1); 它可以正常工作,但是我想知道是否有某些最终案例可能会失败? 当然,我们欢迎您提供其他优雅的解决方案以及左修剪解决方案。 回答1 编辑自c ++ 17起,标准库的某些部分已删除。 幸运的是,从c ++ 11开始,我们有了lambda,它们是一种出色的解决方案。 #include <algorithm> #include <cctype> #include <locale> // trim from start (in place) static inline void ltrim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); } // trim from end (in place) static inline void rtrim(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch)
  • 将SQL保留在存储的Procs与代码中有什么优缺点?(What are the pros and cons to keeping SQL in Stored Procs versus Code [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 7年前关闭。 已锁定。 该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。 它目前不接受新的答案或互动。 将SQL保留在C#源代码或存储的Procs中有哪些优点/缺点? 我一直在和一个我们正在开发的开源项目的朋友讨论这个问题(C#ASP.NET论坛)。 目前,大多数数据库访问是通过在C#中构建SQL内联并调用SQL Server DB来完成的。 因此,我正在尝试确定对于该特定项目而言哪一个是最佳的。 到目前为止,我有: 在Code中的优势: 易于维护-无需运行SQL脚本即可更新查询移植到另一个数据库更容易-没有proc移植到端口 存储过程的优点: 表现安全 回答1 我不喜欢存储过程 存储过程具有更多的可维护性,因为:*每当您想更改某些SQL时,您都不必重新编译C#应用程序 无论如何,当数据类型更改,或者想要返回额外的列或其他内容时,最终还是要重新编译它。 总体上,您可以从应用程序下方“透明地”更改SQL的次数非常少 您最终将重用SQL代码。 包括C#在内的编程语言具有令人称奇的功能,称为函数。 这意味着您可以从多个位置调用同一代码块! 惊人的! 然后,您可以将可重用的SQL代码放入其中之一,或者,如果您想获得真正的高科技,则可以使用为您提供帮助的库。 我相信它们被称为“对象关系映射器”,并且如今非常普遍。
  • Rails:如何在ActiveRecord中设置默认值?(Rails: How can I set default values in ActiveRecord?)
    问题 如何在ActiveRecord中设置默认值? 我从Pratik看到一篇帖子,描述了一个丑陋,复杂的代码块:http://m.onkey.org/2007/7/24/how-to-set-default-values-in-your-model class Item < ActiveRecord::Base def initialize_with_defaults(attrs = nil, &block) initialize_without_defaults(attrs) do setter = lambda { |key, value| self.send("#{key.to_s}=", value) unless !attrs.nil? && attrs.keys.map(&:to_s).include?(key.to_s) } setter.call('scheduler_type', 'hotseat') yield self if block_given? end end alias_method_chain :initialize, :defaults end 我看过以下示例: def initialize super self.status = ACTIVE unless self.status end 和 def after_initialize return
  • Django中业务逻辑和数据访问的分离(Separation of business logic and data access in django)
    问题 我正在Django中编写一个项目,我看到80%的代码在文件models.py 。 这段代码令人困惑,并且在一段时间之后,我不再了解实际发生的事情。 这是困扰我的事情: 我发现模型级别(应该只负责处理数据库中的数据)在发送电子邮件,使用API​​到其他服务等方面也很丑陋。 另外,我发现在视图中放置业务逻辑也是不可接受的,因为这样很难控制。 例如,在我的应用程序中,至少有三种方法可以创建User新实例,但从技术上讲,它应统一创建它们。 我并不总是注意到模型的方法和属性何时变得不确定,以及何时出现副作用。 这是一个简单的例子。 最初, User模型是这样的: class User(db.Models): def get_present_name(self): return self.name or 'Anonymous' def activate(self): self.status = 'activated' self.save() 随着时间的流逝,它变成了: class User(db.Models): def get_present_name(self): # property became non-deterministic in terms of database # data is taken from another service by api return
  • 在活动之间共享数据的最佳方法是什么?(What's the best way to share data between activities?)
    问题 我有一个活动,它是整个应用程序中使用的主要活动,它具有许多变量。 我还有另外两个活动,我希望能够使用第一个活动中的数据。 现在我知道我可以做这样的事情: GlobalState gs = (GlobalState) getApplication(); String s = gs.getTestMe(); 但是我想共享很多变量,有些可能很大,所以我不想像上面那样创建它们的副本。 有没有一种方法可以直接获取和更改变量而无需使用get和set方法? 我记得在Google开发者网站上读过一篇文章,建议不要在Android上使用此功能。 回答1 这里是实现此目的的最常用方法的汇编: 在意图内发送数据静态场 HashMap的WeakReferences 持久对象(sqlite,共享首选项,文件等) TL; DR :有两种共享数据的方式:在Intent的Extras中传递数据或将其保存在其他地方。 如果数据是基元,字符串或用户定义的对象,则将其作为附加意图的一部分发送(用户定义的对象必须实现Parcelable )。 如果传递复杂对象,则将实例保存在其他位置的一个实例中,然后从启动的活动中访问它们。 有关如何以及为何实施每种方法的一些示例: 在意图内发送数据 Intent intent = new Intent(FirstActivity.this, SecondActivity
  • ASP.NET MVC: Custom Validation by DataAnnotation(ASP.NET MVC: Custom Validation by DataAnnotation)
    问题 我有一个具有4个字符串类型属性的模型。 我知道您可以使用StringLength批注来验证单个属性的长度。 但是,我想验证合并的4个属性的长度。 用数据注释执行此操作的MVC方法是什么? 我之所以这样问是因为我是MVC的新手,并且想在制作自己的解决方案之前以正确的方式进行操作。 回答1 您可以编写一个自定义验证属性: public class CombinedMinLengthAttribute: ValidationAttribute { public CombinedMinLengthAttribute(int minLength, params string[] propertyNames) { this.PropertyNames = propertyNames; this.MinLength = minLength; } public string[] PropertyNames { get; private set; } public int MinLength { get; private set; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var properties = this
  • RESTful编程到底是什么?(What exactly is RESTful programming?)
    问题 RESTful编程到底是什么? 回答1 一种称为REST(代表性状态转移)的架构风格主张Web应用程序应使用最初设想的HTTP。 查找应使用GET请求。 PUT,POST和DELETE请求应分别用于突变,创建和删除。 REST支持者倾向于使用URL,例如 http://myserver.com/catalog/item/1729 但是REST体系结构不需要这些“漂亮的URL”。 带有参数的GET请求 http://myserver.com/catalog?item=1729 就像RESTful一样。 请记住,决不要将GET请求用于更新信息。 例如,用于将商品添加到购物车的GET请求 http://myserver.com/addToCart?cart=314159&item=1729 不合适。 GET请求应该是幂等的。 也就是说,两次发出请求应该与一次发出请求没有什么不同。 这就是使请求可缓存的原因。 “添加到购物车”请求不是幂等的-发出两次请求会将该商品的两个副本添加到购物车。 在这种情况下,POST请求显然是适当的。 因此,即使是RESTful Web应用程序也需要其POST请求共享。 这摘自David M. Geary撰写的出色的《 Core JavaServer Faces》一书。 回答2 REST是Web的基础架构原理。 关于Web的神奇之处在于,客户端(浏览器
  • 在神经网络中训练,验证和测试集之间有什么区别?(What's is the difference between train, validation and test set, in neural networks?)
    问题 我正在使用该库来实现学习代理。 我已经生成了训练案例,但是我不确定是什么验证和测试集。 老师说: 培训案例应占70%,测试案例应占10%,验证案例应占20%。 编辑 我有此训练代码,但我不知道何时停止训练。 def train(self, train, validation, N=0.3, M=0.1): # N: learning rate # M: momentum factor accuracy = list() while(True): error = 0.0 for p in train: input, target = p self.update(input) error = error + self.backPropagate(target, N, M) print "validation" total = 0 for p in validation: input, target = p output = self.update(input) total += sum([abs(target - output) for target, output in zip(target, output)]) #calculates sum of absolute diference between target and output accuracy.append
  • 如何在WordPress中添加PHP页面?(How can I add a PHP page to WordPress?)
    问题 我想为我的WordPress博客创建一个自定义页面,该页面将在其中执行我的PHP代码,同时保留整个网站CSS /主题/设计的一部分。 PHP代码将使用第三方API(因此我需要包含其他PHP文件)。 我该如何完成? 注意:我没有与WordPress API交互的特定需求-除了包括某些其他PHP库之外,我还需要在WordPress页面中包含的PHP代码中没有其他依赖项。 因此,很明显,任何不需要学习WordPress API的解决方案都是最好的。 回答1 您无需与API交互或使用插件。 首先,在主题文件夹(在/wp-content/themes/themename/ )中复制post.php或page.php 。 将新文件重命名为templatename.php (其中templatename是您要称为新模板的名称)。 要将新模板添加到可用模板列表中,请在新文件顶部输入以下内容: <?php /* Template Name: Name of Template */ ?> 您可以修改该文件(使用PHP)以包括其他文件或任何您需要的文件。 然后在WordPress博客中创建一个新页面,在页面编辑屏幕中,您会在右侧的Attributes小部件中看到一个Template下拉列表。 选择您的新模板并发布页面。 您的新页面将使用templatename.php定义的PHP代码。 来源