특정 상황에서 필수 유효성 검사 속성 비활성화


138

특정 컨트롤러 작업에서 필수 유효성 검사 특성을 비활성화 할 수 있는지 궁금합니다. 편집 양식 중 하나에서 사용자가 이전에 이미 지정한 필드의 값을 입력하지 않아도되기 때문에 이것이 궁금합니다. 그러나 값을 입력 할 때 값을 해시하는 등의 특수 논리를 사용하여 모델을 업데이트하는 논리를 구현합니다.

이 문제를 해결하는 방법에 대한 의견이 있으십니까?

편집 :
네, 클라이언트 유효성 검사는 여기에 문제가 있습니다. 값을 입력하지 않고 양식을 제출할 수 없기 때문입니다.


3
+1 good Q. 여기서 클라이언트 검증을 언급하면 ​​좋을 것입니다. 한 가지 옵션은 RequiredAttr완전히 제거하고 필요할 때 서버 측 점검을 수행하는 것입니다. 그러나 이것은 고객에게 까다로울 것입니다
— 기드온

4
클라이언트 유효성 검사 에서 특정 필드 비활성화 (jquery 유효성 검사에 대한 참조 제거 없음)를 다루는 모든 사람을위한 포인트
— gideon

어쩌면 내가 요점을 잃어 버렸을 수도 있지만 사용자가 이미 값을 이미 지정한 경우 해당 값이 이미 존재하므로 필수 유효성 검사를 통과합니다. 다른 의미가 있었습니까?
— Erik Funkenbusch

이 값은 암호 및 보안 응답과 같이 해시되었으므로 편집 양식에 새 값을 입력하면 삽입하기 전에 새 값을 다시 해시하고 싶지만 옵션을 비워 둘 수 있습니다. 말하자면.
— Alex Hope O'Connor 2

1
@gideon : Adrian Smith의 답변 참조 : stackoverflow.com/a/9781066/114029
— Leniel Maccaferri

답변:


76

이 문제는 뷰 모델을 사용하여 쉽게 해결할 수 있습니다. 뷰 모델은 주어진 뷰의 요구에 맞게 특별히 설계된 클래스입니다. 예를 들어 귀하의 경우 다음과 같은 뷰 모델을 가질 수 있습니다.

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)
{
    ...
}

널 입력 가능하지 않은 부울 / 비트가있는 경우 항상 참이 아닙니다. 그러나 실제로는 참 또는 거짓으로 끝나기 때문에 차이를 만들지 않습니다. CSS를 사용하여 필수 필드를 강조 표시하고 CheckBoxFor 항목을 잘못 강조 표시했습니다. 내 솔루션 : $ ( "# IsValueTrue"). removeAttr ( "data-val-required");
— Robert Koch

업데이트에는 일반적으로 (FormCollection 컬렉션)이 있습니다. 모델을 매개 변수로 사용하는 방법을 설명해 주시겠습니까?
— Raj Kumar

4
아니요, 우리는 보통 Update(FormCollection collection)적어도 없습니다. 항상 특정 뷰 모델을 정의하고 사용합니다 Update(UpdateViewView model).
— Darin Dimitrov 2016 년

동일한 HTTP 동작을 가진 오버로드 메소드는 허용되지 않으므로 나에게는 이것이 작동하지 않는 것 같습니다. 뭔가 빠졌습니까?
— e11s December

@edgi, 아니오, 당신은 아무것도 빠지지 않았습니다. 내 게시물에 실수가 있습니다. 두 번째 조치 방법은 분명히 호출되어야합니다 Insert. 이것을 지적 해 주셔서 감사합니다.
— Darin Dimitrov

55

클라이언트 측에서 단일 필드에 대한 유효성 검증을 사용하지 않으려면 다음과 같이 유효성 검증 속성을 대체 할 수 있습니다.

@Html.TexBoxFor(model => model.SomeValue, 
                new Dictionary<string, object> { { "data-val", false }})

20
jQuery를 통해 나를 위해 일한 것은 : $ ( "# SomeValue"). removeAttr ( "data-val-required");
— Robert Koch

6
이 방법이 마음에 들지만 다음을 사용하여 양식 유효성 검사 특성을 다시 구문 분석해야했습니다. $ ( 'form'). removeData ( 'unobtrusiveValidation'); $ ( 'form'). removeData ( 'validator'); $ .validator.unobtrusive.parse ( '양식 선택기');
— Yannick

15
@Html.TexBoxFor(model => model.SomeValue, new { data_val = false })-읽기 쉬운 IMO.
— eth0

나는이 방법을 대부분 좋아하여 각 필드를 미세하게 제어 할 수있게했지만 POST로 저장할 데이터를 보낼 때 ModelState.IsValid를 취소하기 위해 추가 할 수 있습니다. 어쩌면 어떤 위험을 일으킬 수 있습니까?
— Felipe FMMobile

4
jQuery를 통해 비활성화하려면 :$(".search select").attr('data-val', false);
— Leniel Maccaferri

40

나는이 질문이 오래 전에 답변되어 왔으며 수락 된 답변이 실제로 작업을 수행한다는 것을 알고 있습니다. 그러나 나를 귀찮게하는 한 가지가 있습니다 : 유효성 검사를 비활성화하기 위해 2 개의 모델 만 복사하면됩니다.

내 제안은 다음과 같습니다.

public class InsertModel
{
    [Display(...)]
    public virtual string ID { get; set; }

    ...Other properties
}

public class UpdateModel : InsertModel
{
    [Required]
    public override string ID
    {
        get { return base.ID; }
        set { base.ID = value; }
    }
}

이런 식으로 클라이언트 / 서버 측 유효성 검사를 신경 쓸 필요가 없으며 프레임 워크는 예상대로 작동합니다. 또한 [Display]기본 클래스에서 속성 을 정의하는 경우에 속성을 다시 정의하지 않아도됩니다 UpdateModel.

그리고이 클래스들을 여전히 같은 방식으로 사용할 수 있습니다 :

[HttpPost]
public ActionResult Update(UpdateModel model)
{
    ...
}

[HttpPost]
public ActionResult Insert(InsertModel model)
{
    ...
}

특히 유효성 검사 목록이 긴 경우이 방법이 더 좋습니다. 예를 들어, 기본 클래스에 더 많은 속성을 추가하여 이점을보다 분명하게 얻을 수 있습니다. 내가 볼 수있는 유일한 단점은 속성을 상속하여 속성을 재정의 할 수있는 방법이 없다는 것입니다. 예를 들어, 기본 클래스에 [필수] 속성이있는 경우 사용자 지정 [선택 사항] 속성이 없으면 상속 속성도 [필수]가됩니다.
— Yorro

여러 속성을 가진 'Project'개체가있는 viewModel이 있지만 특정 상황에서 이러한 속성 중 하나만 유효성 검사하기를 원하지만 이와 같은 것을 생각했습니다. 객체의 속성을 무시할 수 있다고 생각하지 않습니까? 어떤 충고?
— vincent de g

속성을 재정의 할 수 없습니다. 기본 클래스는 모든 하위 클래스에 대한 공통 속성 만 포함해야합니다. 그런 다음 하위 클래스는 필요한 속성을 정의해야합니다.
— PhilDulac

1
가장 우아하고 재사용 가능한 명확한 솔루션. 복제가 잘못되었습니다. 다형성이 방법입니다. +1
— T-moty

필자의 경우 기본 클래스에는 필수 속성이 있으며 부모 클래스에서 필요하지 않은 속성으로 만들고 싶습니다. 모델의 사본 두 개가 없어도 가능합니까?
— Alexey Strakh

27

컨트롤러 작업에서 다음을 사용하여 속성에서 모든 유효성 검사를 제거 할 수 있습니다.

ModelState.Remove<ViewModel>(x => x.SomeProperty);

MVC5에 관한 @Ian 의 의견

다음은 여전히 ​​가능합니다

ModelState.Remove("PropertyNameInModel");

업데이트 된 API로 정적 타이핑을 잃어 버리는 것이 조금 귀찮습니다. HTML 헬퍼 인스턴스를 작성하고 NameExtensions Methods를 사용하여 이전 방식과 유사한 것을 달성 할 수 있습니다.


빼고 ... ModelState그 서명과 일치 하는 방법이 없습니다 . 적어도 MVC 5에는 없습니다.
— Ian Kemp

문제는 모든 유효성 검사를 제거하는 방법이 아닙니다. 필수 필드 유효성 검사를 제거하는 방법이었습니다. 다른 유효성 검사 규칙을 그대로두고이 작업을 수행 할 수 있습니다.
— Richard

15

고객 쪽 양식에 대한 유효성 검사를 비활성화하기 위해 내 연구에 기반한 여러 옵션이 아래에 나와 있습니다. 그들 중 하나가 희망적으로 당신을 위해 일할 것입니다.

옵션 1

나는 이것을 선호하며 이것은 완벽하게 작동합니다.

(function ($) {
    $.fn.turnOffValidation = function (form) {
        var settings = form.validate().settings;

        for (var ruleIndex in settings.rules) {
            delete settings.rules[ruleIndex];
        }
    };
})(jQuery); 

그리고 그것을 호출

$('#btn').click(function () {
    $(this).turnOffValidation(jQuery('#myForm'));
});

옵션 2

$('your selector here').data('val', false);
$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

옵션 3

var settings = $.data($('#myForm').get(0), 'validator').settings;
settings.ignore = ".input";

옵션 4

 $("form").get(0).submit();
 jQuery('#createForm').unbind('submit').submit();

옵션 5

$('input selector').each(function () {
    $(this).rules('remove');
});

서버 측

속성을 작성하고 해당 속성으로 조치 메소드를 표시하십시오. 특정 요구에 맞게이를 사용자 정의하십시오.

[AttributeUsage(AttributeTargets.All)]
public class IgnoreValidationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var modelState = filterContext.Controller.ViewData.ModelState;

        foreach (var modelValue in modelState.Values)
        {
            modelValue.Errors.Clear();
        }
    }
}

더 나은 접근법은 여기에서 설명 합니다 .mvc 서버 측 유효성 검사를 동적으로 활성화 / 비활성화


$ ( '입력 선택기') .each (function () {$ (this) .rules ( 'remove');}); 나를 도와주었습니다
— Sachin Pakale

문제는 특히 모든 유효성 검사를 제거하는 것이 아니라 필수 필드 유효성 검사를 제거하는 것에 관한 것입니다. 귀하의 답변은 모든 유효성 검사를 제거하는 것입니다.
— Richard

14

개인적으로 나는 Darin Dimitrov가 그의 해결책에서 보여준 접근법을 사용하는 경향이 있습니다. 이를 통해 데이터 주석 접근 방식을 유효성 검사와 함께 사용할 수 있고 각 작업에 해당하는 각 ViewModel에 대해 별도의 데이터 속성을 가질 수 있습니다. 모델과 뷰 모델 간의 복사 작업량을 최소화하려면 AutoMapper 또는 ValueInjecter를 살펴 보십시오 . 둘 다 각자의 장점이 있으므로 확인하십시오.

IValidatableObject에서 뷰 모델 또는 모델을 파생시키는 다른 방법이 있습니다. 이를 통해 Validate 함수를 구현할 수 있습니다. 유효성 검사에서 유효성 검사 결과 요소 목록을 반환하거나 유효성 검사에서 탐지 한 각 문제에 대해 수익률을 반환 할 수 있습니다.

ValidationResult는 오류 메시지와 필드 이름이 포함 된 문자열 목록으로 구성됩니다. 오류 메시지는 입력 필드 근처의 위치에 표시됩니다.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
  if( NumberField < 0 )
  {
    yield return new ValidationResult( 
        "Don't input a negative number", 
        new[] { "NumberField" } );
  }

  if( NumberField > 100 )
  {
    yield return new ValidationResult( 
        "Don't input a number > 100", 
        new[] { "NumberField" } );
  }

  yield break;
}

이것을 클라이언트쪽에 연결할 수 있습니까?
— Muhammad Adeel Zahid

클라이언트 측 유효성 검사는 일반적으로 개별 필드에 대해서만 수행되며 대화 형의 필드 별 유효성 검사 피드백을 사용자 편의를 위해 수행합니다. 객체 유효성 검사 단계에는 일반적으로 종속 유효성 검사 (객체 자체 외부에있는 다중 필드 및 / 또는 조건)가 포함되므로 코드를 JavaScript로 컴파일 할 수 있더라도 클라이언트 쪽에서 반드시 수행 할 필요는 없습니다. 클라이언트 측의 복잡한 / 종속적 유효성 검사로 인해 가치가 추가되면 onsubmit 콜백을 사용하고 클라이언트 측에서 유효성 검사 논리를 복제해야합니다.
— mindplay.dk

7

내가 생각하는 가장 깨끗한 방법은 클라이언트 측 유효성 검사를 비활성화하고 서버 측에서 다음을 수행해야한다는 것입니다.

  1. ModelState [ "SomeField"]. Errors.Clear (컨트롤러에서 또는 컨트롤러 코드가 실행되기 전에 오류를 제거하기위한 작업 필터를 만듭니다)
  2. 감지 된 문제의 위반을 감지하면 컨트롤러 코드에서 ModelState.AddModelError를 추가하십시오.

여기에 사용자 정의보기 모델조차도 '사전 응답 된'필드의 수가 다양 할 수 있기 때문에 문제를 해결하지 못하는 것 같습니다. 그렇지 않으면 사용자 정의보기 모델이 가장 쉬운 방법 일 수 있지만 위의 기술을 사용하면 유효성 검사 문제를 해결할 수 있습니다.


1
이것은 내가 필요한 것입니다. 하나의보기가 있었고이보기에서 다른 동작이 발생하므로 다른 ViewModel로 볼 수 없었습니다. 이것은 매력처럼 작동합니다
— ggderas

6

이것은 의견에 대한 다른 사람의 대답이었습니다 ... 그러나 진정한 대답이어야합니다.

$("#SomeValue").removeAttr("data-val-required")

[Required]속성 이있는 필드를 사용하여 MVC 6에서 테스트

위의 https://stackoverflow.com/users/73382/rob 에서 도난당한 답변


1
서버 측 유효성 검사는 어떻습니까?
— T-moty 2016 년

ModelState. 제거, 그렇지? 어쨌든, 문제는 내 모델에 두 번째 엔터티가 포함되어 있다는 것입니다 ... 주요 검증을 원했지만 보조는 해당 페이지에서 검증이 필요하지 않았습니다. JQuery 만 필요했습니다.
— Mike_Matthews_II

링크가 깨 졌다고 생각하므로 수정하십시오. 이것은 부분 답변입니다.
— T-moty 2016 년

이것이 MVC6에서 작동한다고 말한 것이 이상합니다 (현재 MVC6에서 테스트 할 수있는 옵션이 없습니다). 현재 사용중인 MVC4에서는 작동하지 않습니다.
— eaglei22

질문은 MVC / C #에 대한 것입니다
— -JS

2

내 모델에 대한 편집 뷰를 생성 할 때이 문제가 발생하여 하나의 필드 만 업데이트하려고합니다.

가장 간단한 방법에 대한 내 솔루션은 다음을 사용하여 두 필드를 넣는 것입니다.

 <%: Html.HiddenFor(model => model.ID) %>
 <%: Html.HiddenFor(model => model.Name)%>
 <%: Html.HiddenFor(model => model.Content)%>
 <%: Html.TextAreaFor(model => model.Comments)%>

주석은 편집보기에서만 업데이트하며 필수 속성이없는 필드입니다.

ASP.NET MVC 3 엔터티


1

AFAIK 런타임에 속성을 제거 할 수는 없지만 값만 변경하십시오 (예 : readonly true / false) 비슷한 것을 찾으십시오 . 속성을 엉망으로하지 않고 원하는 것을 수행하는 또 다른 방법으로 특정 작업에 대해 ViewModel을 사용하여 다른 컨트롤러에 필요한 로직을 손상시키지 않고 모든 로직을 삽입 할 수 있습니다. 일종의 마법사 (다단계 양식)를 얻으려고하면 이미 컴파일 된 필드를 직렬화하고 TempData를 사용하여 단계를 수행하십시오. (직렬화 직렬화를 돕기 위해 MVC 선물을 사용할 수 있습니다 )


1

@Darin이 말한 것은 내가 추천하는 것입니다. 그러나 실제로 비트, 부울, Guid와 같은 기본 유형에 단순히이 null을 허용 하여이 유형을 사용하는 경우 에도이 방법을 사용할 수 있다고 덧붙였습니다. 이 작업을 수행하면 Required속성 이 예상대로 작동합니다.

public UpdateViewView
{
    [Required]
    public Guid? Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public int? Age { get; set; }
    [Required]
    public bool? IsApproved { get; set; }
    //... some other properties
}

1

MVC 5부터는 이것을에 추가하면 쉽게 얻을 수 있습니다 global.asax.

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

1

웹 API에서 삽입 및 업데이트에 동일한 모델을 사용할 수있는 솔루션을 찾고있었습니다. 내 상황에서 이것은 항상 본문 내용입니다. [Requiered]이 업데이트 방법 인 경우 속성은 생략해야합니다. 내 솔루션에서는 [IgnoreRequiredValidations]메소드 위에 속성을 배치합니다 . 이것은 다음과 같습니다 :

public class WebServiceController : ApiController
{
    [HttpPost]
    public IHttpActionResult Insert(SameModel model)
    {
        ...
    }

    [HttpPut]
    [IgnoreRequiredValidations]
    public IHttpActionResult Update(SameModel model)
    {
        ...
    }

    ...

다른 무엇을해야합니까? 시작시 자체 BodyModelValidator를 작성하고 추가해야합니다. 이것은 HttpConfiguration에 있으며 다음과 같습니다.config.Services.Replace(typeof(IBodyModelValidator), new IgnoreRequiredOrDefaultBodyModelValidator());

using Owin;
using your_namespace.Web.Http.Validation;

[assembly: OwinStartup(typeof(your_namespace.Startup))]

namespace your_namespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Configuration(app, new HttpConfiguration());
        }

        public void Configuration(IAppBuilder app, HttpConfiguration config)
        {
            config.Services.Replace(typeof(IBodyModelValidator), new IgnoreRequiredOrDefaultBodyModelValidator());
        }

        ...

내 자신의 BodyModelValidator는 DefaultBodyModelValidator에서 파생됩니다. 그리고 나는 'ShallowValidate'방법을 재정의해야한다는 것을 알았습니다. 이 재정의에서 필요한 모델 유효성 검사기를 필터링합니다. 그리고 이제 IgnoreRequiredOrDefaultBodyModelValidator 클래스와 IgnoreRequiredValidations 속성 클래스 :

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata;
using System.Web.Http.Validation;

namespace your_namespace.Web.Http.Validation
{
    public class IgnoreRequiredOrDefaultBodyModelValidator : DefaultBodyModelValidator
    {
        private static ConcurrentDictionary<HttpActionBinding, bool> _ignoreRequiredValidationByActionBindingCache;

        static IgnoreRequiredOrDefaultBodyModelValidator()
        {
            _ignoreRequiredValidationByActionBindingCache = new ConcurrentDictionary<HttpActionBinding, bool>();
        }

        protected override bool ShallowValidate(ModelMetadata metadata, BodyModelValidatorContext validationContext, object container, IEnumerable<ModelValidator> validators)
        {
            var actionContext = validationContext.ActionContext;

            if (RequiredValidationsIsIgnored(actionContext.ActionDescriptor.ActionBinding))
                validators = validators.Where(v => !v.IsRequired);          

            return base.ShallowValidate(metadata, validationContext, container, validators);
        }

        #region RequiredValidationsIsIgnored
        private bool RequiredValidationsIsIgnored(HttpActionBinding actionBinding)
        {
            bool ignore;

            if (!_ignoreRequiredValidationByActionBindingCache.TryGetValue(actionBinding, out ignore))
                _ignoreRequiredValidationByActionBindingCache.TryAdd(actionBinding, ignore = RequiredValidationsIsIgnored(actionBinding.ActionDescriptor as ReflectedHttpActionDescriptor));

            return ignore;
        }

        private bool RequiredValidationsIsIgnored(ReflectedHttpActionDescriptor actionDescriptor)
        {
            if (actionDescriptor == null)
                return false;

            return actionDescriptor.MethodInfo.GetCustomAttribute<IgnoreRequiredValidationsAttribute>(false) != null;
        } 
        #endregion
    }

    [AttributeUsage(AttributeTargets.Method, Inherited = true)]
    public class IgnoreRequiredValidationsAttribute : Attribute
    {

    }
}

출처 :



0

필자의 경우 동일한 모델이 많은 페이지에서 재사용을 위해 사용되었습니다. 그래서 내가 한 것은 제외를 확인하는 사용자 정의 속성을 만들었습니다.

public class ValidateAttribute : ActionFilterAttribute
{
    public string Exclude { get; set; }
    public string Base { get; set; }
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!string.IsNullOrWhiteSpace(this.Exclude))
        {
            string[] excludes = this.Exclude.Split(',');
            foreach (var exclude in excludes)
            {
                actionContext.ModelState.Remove(Base + "." + exclude);
            }
        }
        if (actionContext.ModelState.IsValid == false)
        {
            var mediaType = new MediaTypeHeaderValue("application/json");
            var error = actionContext.ModelState;

            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, error.Keys, mediaType);

        }
    }
}

컨트롤러에서

[Validate(Base= "person",Exclude ="Age,Name")]
    public async Task<IHttpActionResult> Save(User person)
    {

            //do something           

    }

모델이

public class User
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Range(18,99)]
    public string Age { get; set; }
    [MaxLength(250)]
    public string Address { get; set; }
}

-1

예, 필수 속성을 비활성화 할 수 있습니다. RequiredAtribute에서 확장 할 수 있도록 고유 한 사용자 지정 클래스 특성 (ChangeableRequired라는 샘플 코드)을 만들고 Disabled 속성을 추가하고 IsValid 메서드를 재정 의하여 기밀이 있는지 확인합니다. 다음과 같이 반사를 사용하여 비활성화 된 poperty를 설정하십시오.

맞춤 속성 :

namespace System.ComponentModel.DataAnnotations
{
    public class ChangeableRequired : RequiredAttribute
    {
       public bool Disabled { get; set; }

       public override bool IsValid(object value)
       {
          if (Disabled)
          {
            return true;
          }

          return base.IsValid(value);
       }
    }
}

새 사용자 정의 속성을 사용하도록 속성을 업데이트하십시오.

 class Forex
 {
 ....
    [ChangeableRequired]
    public decimal? ExchangeRate {get;set;}
 ....
 }

속성을 사용하지 않으려면 리플렉션을 사용하여 설정하십시오.

Forex forex = new Forex();
// Get Property Descriptor from instance with the Property name
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(forex.GetType())["ExchangeRate"];
//Search for Attribute
ChangeableRequired attrib =  (ChangeableRequired)descriptor.Attributes[typeof(ChangeableRequired)];

// Set Attribute to true to Disable
attrib.Disabled = true;

기분이 좋고 깨끗합니까?

NB : 객체 인스턴스가 활성화되어있는 동안 위의 유효성 검사가 비활성화됩니다 ...


이에 대해 몇 가지 토론을 한 후 유효성 검사 비활성화를 권장하지 않고 규칙을 검토한다고 언급하고 싶습니다. 비활성화하면 규칙을 다시 활성화하기 위해 종속성을 생성하므로 규칙을 검토하는 것이 좋습니다.
— 어니스트 Gunning

동일한 프로세스 내에서 실행되는 해당 필드의 모든 유효성 검사를 완전히 비활성화하기 위해 정적 값을 변경하면 끔찍한 아이디어처럼 들립니다.
— Jeremy Lakeman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.