ASP.NET MVC: Types Used in Model Binding

Is there a way to pass a parameter to a controller action from one type to another in ASP.NET MVC 5?

Example. The method of action is as follows:

public string Test(Guid input) { return ""; } 

If the method is called with the parameters "input = hello", then I get an error: "The parameter dictionary contains a zero entry for the parameter" input "of the non-empty type" System.Guid "for the method 'System.String Test (System.Guid)' in 'RealtyGuide.WebSite.Controllers.HomeController'. The optional parameter must be a reference type, null type, or declared as an optional parameter. "

What I want is to try passing the Guid parameter according to the specific (custom) rules. Is this a question about model binding? What are the possible ways to solve this problem? Sorry for my English.

About the answers . If you just want to assign null to the Guid parameter, if it is not valid, check out this answer . If you are looking for an example of a custom binder, check out this and this .

0
source share
4 answers

According to comments from @AndreiV and @AntP solutions:

  • if the string is a valid Guid string, then it will bind automatically (nothing else is required)

  • if the string is not a valid Guid string, then

2.1. make a conversion to the body of the action (in my opinion, this entails duplication of code) or

2.2. Set up a custom (user-defined) model binder. Below is the code for the latter approach (model binder).

 // This is an example. // Note the returning of null which is undesired. // Also it does not deal with exceptions handling. Use it only as a stub. public class ExtendedModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (!(bindingContext.ModelType == typeof(Guid))) return base.BindModel(controllerContext, bindingContext); if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) return null; string input = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue; if (string.IsNullOrEmpty(input)) return null; Guid g; if (Guid.TryParse(input, out g)) return g; var bytes = HttpServerUtility.UrlTokenDecode(s); var result = new Guid(bytes); return result; } } 

You must register with Application_Start:

 ModelBinders.Binders.Add(typeof(Guid), new RealtyGuide.WebSite.Extensions.MyModelBinder()); 

You can use attributes instead of registering the binder globally (see here ), but I will not use it because it entails unnecessary duplication of code in my task.

Refs: 1 , 2 , 3

+2
source

In response to the Hoborg example, https://stackoverflow.com/posts/26676337/revisions the following will return null values ​​or the Guid parameter, if necessary.

 public class NullableGuidBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType == typeof(Guid?)) { var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); string input = valueResult.AttemptedValue; if (string.IsNullOrEmpty(input) || input == "0") { // return null, even if input = 0 // however, that is dropdowns' "guid.empty") // base.BindModel(...) would fail converting string to guid, // Guid.Parse and Guid.TryParse would fail since they expect 000-... format // add the property to modelstate dictionary var modelState = new ModelState { Value = valueResult }; bindingContext.ModelState.Add(bindingContext.ModelName, modelState); return null; } } return base.BindModel(controllerContext, bindingContext); } } 

as indicated in your controller

  [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> SelectAction( [ModelBinder(typeof(NullableGuidBinder))] Guid? id) { // your stuff } 
+2
source

I came across this question when looking for a Guid binding in action with a graceful digression when the value is invalid. If the actual value provided should not be known, the use of the nullable Guid ( Guid? ) Tag should be performed. For instance. (this is verified in the ASP.NET Web API):

 [Route("Test")] [HttpGet] public string Test(Guid? input = null) 

If a valid Guid provided, the entry will be filled. Otherwise, it will be null .

+1
source

Attempting to enter = "helo" is the wrong method. Guid should contain an example with a 32-bit number (12345678910111213141516171819202)

Try this input = 12345678910111213141516171819202, Attaching the value as a 32-digit number, the Guid value takes it. then the method will not display the same error.

 var input = 12345678910111213141516171819202; public string Test(Guid input) { return ""; } 
0
source

Source: https://habr.com/ru/post/1335488/


All Articles