15
<% using (Html.BeginForm("SubmitUserName")) { %>
    <input type='text' name='user-name' />
    <input type='submit' value='Send' />
<% } %>

What should be a signature of a corresponding Action method to accept user-name parameter?

public ActionResult SubmitUserName(string user-name) {...}

Method signature above does not work for some reason ;-)

I know there is an ActionNameAttribute to handle situation with a dash in action name. Is there something like ParameterNameAttribute?

4
  • Do you really need to use dash? Commented Aug 11, 2010 at 18:04
  • is it required to be user-name? Commented Aug 11, 2010 at 18:05
  • It is not required at all. It just puzzling that MVC didn't think of this scenario. I don't actually use it, just curious if its there...or why it isn't there. Commented Aug 11, 2010 at 19:06
  • 2
    There are scenarios where you're using a third-party tool and you need to support dashes Commented Jun 17, 2019 at 11:25

5 Answers 5

14

Create a pseudo-parameter in the first line of the action method:

public ActionResult SubmitUserName()
{
    string userName = Request.Params["user-name"];
    ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

That didn't even compile for me. Are you talking about ApiController?
Oh silly me, the question is about MVC... and I'm doing Web API. OK then.
13

As everyone has noted, the easiest fix would be not to use a dash. If you truly need the dash, you can create your own ActionFilterAttribute to handle it, though.

Something like:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class ParameterNameAttribute :  ActionFilterAttribute
{
    public string ViewParameterName { get; set; }
    public string ActionParameterName { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if(filterContext.ActionParameters.ContainsKey(ViewParameterName))
        {
            var parameterValue = filterContext.ActionParameters[ViewParameterName];
            filterContext.ActionParameters.Add(ActionParameterName, parameterValue);   
        }
    }
}

You would then apply the filter to the appropriate Action method:

[ParameterName( ViewParameterName = "user-data", ActionParameterName = "userData")]
[ParameterName( ViewParameterName = "my-data", ActionParameterName = "myData" )]
    public ActionResult About(string userData, string myData)
    {
        return View();
    }

You would probably want to enhance the ParameterNameAttribute to handle upper/lower case, but that would be the basic idea.

1 Comment

OnActionExecuting should use TryGetValue to avoid the double lookup of ContainsKey followed by the indexer.
8

Not answering the actual question based on the technlogy in question, but anyway, the world moves forward in some areas; in AspNetCore.Mvc you can simply do:

    [HttpGet()]
    public ActionResult SubmitUserName( [FromHeader(Name = "user-Name")] string userName) {...}

Comments

3

I found this answer helpful, but I don't know exactly how the provided example helps. It appears to just "rename" a value that the binder all ready provided.

In my case, I was being posted to by an external service that would post something like "body-plain" and I could not control the name. So I modified this sample to look like this:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class ParameterNameMapAttribute : ActionFilterAttribute
{
    public string InboundParameterName { get; set; }
    public string ActionParameterName { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        object value = filterContext.RequestContext.HttpContext.Request[InboundParameterName];

        if (filterContext.ActionParameters.ContainsKey(ActionParameterName))
        {
            filterContext.ActionParameters[ActionParameterName] = value;
        }
        else
        {
            throw new Exception("Parameter not found on controller: " + ActionParameterName);
        }
    }
}

This actually takes in the parameter "body-plain" for example and maps it to an ActionParameter I defined on my controller. Like so:

[ParameterNameMap(InboundParameterName = "body-plain", ActionParameterName = "bodyPlainText")]
    [ParameterNameMap(InboundParameterName = "Thread-Topic", ActionParameterName = "alternateSubject")]
    public HttpStatusCodeResult Process(string token, string timestamp, string signature, string subject, string sender, string recipient, string bodyPlainText, string alternateSubject)
    {

Comments

1

I would suggest doing something like this - unless it's required to use the user-name attribute (or you're not binding to a model)

<% using (Html.BeginForm("SubmitUserName")) { %>
    <%: Html.TextBoxFor(m => m.UserName) %>
    <input type='submit' value='Send' />
<% } %>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.