(MVC) MVC (2018)

The ways to receive complex parameters in ASP.NET


There are some choice to receive parameters in ASP.NET. In this page I'm describe most of it. This is real workable code, therefore as example to first part code below, I'll use this form.


   9:      <form role="form" name="resumeform" id="resumeform" method="post" enctype="multipart/form-data" action="/api/Upload/PostResumeData">
  10:          <div class="col-md-1 panel1" style="border:none">
  11:          </div>
  12:          @Html.Partial("~/Views/Resume/PostSetSkillPanel.vbhtml")
  13:          <div class="col-md-7 panel1">
  14:              <h2>Please fill all fields in your public resume </h2>
  15:              <div style="max-height: 750px; min-height:750px; overflow: auto;">
  16:                  <div class="form-group">
  17:                      <label for="Title"><span style="color:red">*</span> Title of your bean </label>
  18:                      <input class="form-control" id="title" name="title" placeholder="No more than 100 chars.">
  19:                  </div>
  20:                  <div class="form-group">
  21:                      <label for="InputPDFFile">Upload PDF files with your resume</label>
  22:                      <input type="file" class="form-control-file" id="InputPDFFile" name="InputPDFFile">
  23:                      <p class="help-block">This pdf files not will be parsed or changed.</p>
  24:                  </div>
  25:                  <div class="form-group">
  26:                      <label for="InputAvaFile">Upload your Avatar (if necessary)</label>
  27:                      <input type="file" class="form-control-file" id="InputAvaFile" name="InputAvaFile">
  28:                      <p class="help-block">Will be reduced to 100x100 px</p>
  29:                  </div>
  30:                  <div class="form-group">
  31:                      <label for="Short-description"><span style="color:red">*</span> Enter description for customer </label>
  32:                      <textarea class="form-control" id="Short-description" rows="7" placeholder="No more than 1000 chars." name="Short-description"></textarea>
  33:                  </div>
  34:                  <div class="form-group">
  35:                      <label for="Publiccontacts"><span style="color:red">*</span> Enter your public contacts for customer </label>
  36:                      <input class="form-control" id="Publiccontacts" placeholder="Any your public contact in free form, No more than 100 chars." name="Publiccontacts"">
  37:                  </div>
  38:                  <div class="form-group">
  39:                      <label for="AdminContacts">Enter your email for Sign in to this site. </label>
  40:                      <input type="email" class="form-control" id="AdminContacts" placeholder="We sent password to this email." name="AdminContacts">
  41:                      <span style="color:red">*</span> or <br />
  42:                      <label for="Publiccontacts">Sign In using another account</label>
  43:                      <a class="oauth" alt="Sign in using Github" title="Sign in using Github" href="/script/Membership/OAuthLogOn.aspx?auth=GitHub"><img src="/Images/octicons_github-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  44:                      <a class="oauth" alt="Sign in using Linkedin" title="Sign in using Linkedin" href="/script/Membership/OAuthLogOn.aspx?auth=LinkedIn"><img src="/Images/linkedin-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  45:                      <a class="oauth" alt="Sign in using Facebook" title="Sign in using Facebook" href="/script/Membership/OAuthLogOn.aspx?auth=Facebook"><img src="/Images/facebook-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  46:                      <a class="oauth" alt="Sign in using Google" title="Sign in using Google" href="/script/Membership/OAuthLogOn.aspx?auth=Google"><img src="/Images/google-plus-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  47:                      <a class="oauth" alt="Sign in using Microsoft" title="Sign in using Microsoft" href="/script/Membership/OAuthLogOn.aspx?auth=Microsoft"><img src="/Images/microsoft-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  48:                  </div>
  49:                  <button id="PostResume" name="PostResume" type="submit" class="btn btn-primary">Post Resume</button>
  50:              </div>
  51:          </div>
  52:      </form>
  53:  </div>
  54:   

1. WebHandler - the simplest and universal way to receive any parameters in ASP.NET.

First, simplest and common choice is exclude any specific Microsoft complicated superstructure. And receive form parameters with simple ASP.NET Handler (.ASHX). This way I use in most situation when I have difficulties with built in Microsoft processing of parameters. And this is oldest way to receive parameters in ASP.NET MVC, what exist in ASP.NET over 15 years.

Complex parameters usually reading by MultipartParser and there are two way to read simple POST parameters. First way, if POST-parameters packed with rules content type application/x-www-form-urlencoded, it usually receive as context.Request.Form("Prm1"), otherwise its can read as raw stream, like below (this is template of security activator, that receive GUID-string and return 20-chars code for activation program, but in reality, of cource, string 15 is more complex).


   1:  Imports System.Web
   2:  Imports System.Web.Services
   3:   
   4:  Public Class GetCode
   5:      Implements System.Web.IHttpHandler
   6:   
   7:      Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
   8:          Dim Str1 As String
   9:          Using reader = New IO.StreamReader(context.Request.InputStream)
  10:              Str1 = reader.ReadToEnd()
  11:          End Using
  12:          If Not String.IsNullOrWhiteSpace(Str1) Then
  13:              Dim Hash As Byte()
  14:              Using Md5 As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create()
  15:                  Hash = Md5.ComputeHash(Encoding.UTF8.GetBytes(Str1))
  16:              End Using
  17:              Dim RespString As String = Convert.ToBase64String(Hash)
  18:              context.Response.ContentType = "text/plain"
  19:              context.Response.Write(Left(RespString, Len(RespString) - 4))
  20:          End If
  21:      End Sub
  22:   
  23:      ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
  24:          Get
  25:              Return False
  26:          End Get
  27:      End Property
  28:   
  29:  End Class

Post-parameters in this case is sending as raw string, like this.


   1:  Imports System.IO
   2:  Imports System.Net
   3:  Imports System.Text
   ...   
   9:          Dim Html = PostRequest("http://s5.programmer.expert/GetCode.ashx", ID.ToString)
   ...   
  26:      Public Function PostRequest(Url As String, PostData As String)
  27:          Dim Html As String
  28:          Dim ByteArray As Byte() = Encoding.UTF8.GetBytes(PostData)
  29:          Dim Request As HttpWebRequest = CType(WebRequest.Create(Url), HttpWebRequest)
  30:          Request.AutomaticDecompression = DecompressionMethods.GZip
  31:          Request.Method = "POST"
  32:          Request.ContentType = "application/x-www-form-urlencoded"
  33:          Request.ContentLength = ByteArray.Length
  34:          Dim DataStream As Stream = Request.GetRequestStream()
  35:          DataStream.Write(ByteArray, 0, ByteArray.Length)
  36:          DataStream.Close()
  37:          Using Response As HttpWebResponse = CType(Request.GetResponse(), HttpWebResponse)
  38:              Using Stream As Stream = Response.GetResponseStream()
  39:                  Using Reader As StreamReader = New StreamReader(Stream)
  40:                      Html = Reader.ReadToEnd()
  41:                  End Using
  42:              End Using
  43:          End Using
  44:          Return (Html)
  45:      End Function

2. WebAPI - modern alternative way to receive complex parameter without model.

Firstly and main point you must understanding - this way not faster, not better, not simple than any old way is listed in previous point - WEbMethod (from Classic ASP.NET), simple WebHandler or independent library like MultipartFormDataParser - this is only a small additional way to doing the same job.

And second point you must understanding - there are some alternative way with using WebAPI to doing the same job to receive complex multipart/form-data parameters. And third main point - this is a way to receive RAW parameters without Model.

And below you may see my first variant of code. This is simplest way to receive multipart/form-data parameters by MultipartFormDataStreamProvider. This class firstly automatically saved uploaded files to TMP directory and after that move files to right place with right name. And as a result it return name of uploaded files.



   1:  Imports System.Net
   2:  Imports System.Net.Http
   3:  Imports System.Web.Http
   4:   
   5:  Namespace Controllers
   6:      Public Class UploadController
   7:          Inherits ApiController
   8:   
   9:          <HttpPost>
  10:          Public Async Function PostResumeData() As Threading.Tasks.Task(Of HttpResponseMessage)
  11:   
  12:              If Request.Content.IsMimeMultipartContent() Then
  13:                  Dim UploadedFileList As List(Of KeyValuePair(Of String, String)) = Await FileDataReader1("~/App_Data/tmp/", "~/App_Data/")
  14:              End If
  15:   
  16:              Dim Response = Request.CreateResponse(HttpStatusCode.Moved)
  17:              Response.Headers.Location = New Uri("http://localhost:54598/Project/Search") 'Return RedirectToAction("Search", "Project")
  18:              Return Response
  19:   
  20:          End Function
  21:   
  22:          Async Function FileDataReader1(TmpRoot As String, UserRoot As String) As Threading.Tasks.Task(Of List(Of KeyValuePair(Of String, String)))
  23:   
  24:              Dim TmpRootDir As String = HttpContext.Current.Server.MapPath(TmpRoot)
  25:              Dim StreamProvider = New System.Net.Http.MultipartFormDataStreamProvider(TmpRootDir)
  26:              Dim RDR = Await Request.Content.ReadAsMultipartAsync(StreamProvider)
  27:   
  28:              Dim UploadedFileList = New List(Of KeyValuePair(Of String, String))
  29:   
  30:              Try
  31:                  For Each FileData As Net.Http.MultipartFileData In StreamProvider.FileData
  32:   
  33:                      If Not String.IsNullOrWhiteSpace(FileData.Headers.ContentDisposition.FileName) Then
  34:                          'Uploading file
  35:                          Dim FileName = FileData.Headers.ContentDisposition.FileName.Replace("""", "")
  36:                          If Not String.IsNullOrWhiteSpace(FileName) Then
  37:                              Dim UserFileName As String = IO.Path.Combine(HttpContext.Current.Server.MapPath(UserRoot), FileName)
  38:                              IO.File.Move(FileData.LocalFileName, UserFileName)
  39:                              Dim Key1 = FileData.Headers.ContentDisposition.Name.Replace("""", "")
  40:                              UploadedFileList.Add(New KeyValuePair(Of String, String)(Key1, FileName))
  41:                          End If
  42:                      End If
  43:                  Next
  44:   
  45:                  Return UploadedFileList
  46:   
  47:              Catch e As System.Exception
  48:                  Throw New Web.Http.HttpResponseException(e.Message)
  49:              End Try
  50:   
  51:          End Function
  52:   
  53:      End Class
  54:  End Namespace

The second variant of code is more interesting, It still based on task-based programming model wait Async/Await, still parse parameters from the same form. but instead complex class MultipartFormDataStreamProvider is parse directly input content by StreamReader. Therefore additionally to upload files this variant of code is receive simple parameters from form, not only uploaded files.

Also this way give opportunity to receive not only one string parameters, but directly all receiving data to NameValueCollection.



  17:                  Dim FormValues As List(Of KeyValuePair(Of String, String)) = Await FileDataReader2(AddressOf MyFileProcessor)
  57:   
  58:          Async Function FileDataReader2(ByVal FileProcessor As Action(Of String, IO.Stream)) As Threading.Tasks.Task(Of List(Of KeyValuePair(Of String, String)))
  59:   
  60:              Dim StreamContent = New Http.StreamContent(HttpContext.Current.Request.InputStream)
  61:              StreamContent.Headers.ContentType = Net.Http.Headers.MediaTypeHeaderValue.Parse(HttpContext.Current.Request.ContentType)
  62:              Dim StreamProvider = Await StreamContent.ReadAsMultipartAsync()
  63:   
  64:              Dim FormValues = New List(Of KeyValuePair(Of String, String))
  65:   
  66:              Try
  67:                  For Each HttpContent In StreamProvider.Contents
  68:   
  69:                      If Not String.IsNullOrWhiteSpace(HttpContent.Headers.ContentDisposition.FileName) Then
  70:                          Dim FileName = HttpContent.Headers.ContentDisposition.FileName.Replace("""", "")
  71:                          If Not String.IsNullOrWhiteSpace(FileName) Then
  72:                              'Uploading file
  73:                              Using FileContents As IO.Stream = Await HttpContent.ReadAsStreamAsync()
  74:                                  FileProcessor(FileName, FileContents)
  75:                              End Using
  76:                              Dim Key1 = HttpContent.Headers.ContentDisposition.Name.Replace("""", "")
  77:                              FormValues.Add(New KeyValuePair(Of String, String)(Key1, FileName))
  78:                          End If
  79:                      Else
  80:                          'simple value
  81:                          Dim Val1 = Await HttpContent.ReadAsStringAsync
  82:                          Dim Key1 = HttpContent.Headers.ContentDisposition.Name.Replace("""", "")
  83:                          FormValues.Add(New KeyValuePair(Of String, String)(Key1, Val1))
  84:                      End If
  85:                  Next
  86:   
  87:                  Return FormValues
  88:   
  89:              Catch ex As Exception
  90:                  Throw New Web.Http.HttpResponseException(ex.Message)
  91:              End Try
  92:   
  93:          End Function
  94:   
  95:          Private Function MyFileProcessor(FileName As String, FileContents As IO.Stream)
  96:              Dim UserRootDir As String = HttpContext.Current.Server.MapPath("~/App_Data/")
  97:              Dim ResFileName As String = IO.Path.Combine(UserRootDir, FileName)
  98:              Using FS = New IO.FileStream(ResFileName, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
  99:                  FileContents.CopyToAsync(FS)
 100:              End Using
 101:              Return ResFileName
 102:          End Function

There are one small differences to use directly WebHandler and WebApi, so far as WebApi is processed by IIS Route, we must tune RouteConfig class.


   1:  Imports System
   2:  Imports System.Collections.Generic
   3:  Imports System.Linq
   4:  Imports System.Web
   5:  Imports System.Web.Mvc
   6:  Imports System.Web.Routing
   7:   
   8:  Public Module RouteConfig
   9:      Public Sub RegisterRoutes(ByVal routes As RouteCollection)
  10:          routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
  11:   
  12:          routes.MapRoute(
  13:              name:="Default",
  14:              url:="{controller}/{action}/{id}",
  15:              defaults:=New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional}
  16:          )
  17:      End Sub
  18:  End Module

3. Receive data in MVC controller without model (by FormCollection or by Name).

The first way to receive simple parameters without model is using FormCollection class. There are some example in my site with this method.

The second way to receive simple paramers without model is using name of parameters exactly as it named in View (for example - UserID as string, Password as string). Advantage of this type to receive parameters is automatically type casting. This is template of new MVC code controller created by Visual Studio.

Example of this approach you may see in end of page:

4. Receive data in MVC with model.

A good example of receive simple parameters with model you can see in page StudentsController2.vb (Contoso University). If you create controller by scafford template, you can see all of class of your project and you can select class for template for Model what using to thansfer data between view and controller.



But this is extremally simple example. Go ahead to real code.

Firstly, if you using model no sense take simple html-tag in form like <label> or <input>. All MVC concept is buitling across various attributes like Data Annotations, Validation Atributes and other. Therefore first point to take advantage for this way to transfer data between controller and view is creation Model and second point is using special ASP.NET tag in View, like @Html.TextAreaFor and @Html.ValidationMessageFor, which automatically process this attributes for various purposes

Because I use in my project Model first concept, I have no right directly add needed attributes in DB definition (at common this is standard MVVM concept).



Therefore I prepare additional View model with needed attributes.


   1:  Imports System.ComponentModel.DataAnnotations
   2:   
   3:  Public Class ViewResumeModel
   4:   
   5:      <Required(ErrorMessage:="Skills is mandatory.")>
   6:      <StringLength(1000)>
   7:      Public Property Skills As String
   8:   
   9:      <Required(ErrorMessage:="Title is mandatory.")>
  10:      <Display(Name:="Title of your bean", Prompt:="Title of your bean", Description:="No more than 100 chars")>
  11:      <StringLength(100)>
  12:      Public Property Title As String
  13:   
  14:      <DataType(DataType.Upload)>
  15:      <Display(Name:="Upload PDF files with your resume (if necessary)")>
  16:      Public Property InputPDFFile As HttpPostedFileBase
  17:   
  18:      <DataType(DataType.Upload)>
  19:      <Display(Name:="Upload your Avatar (if necessary)")>
  20:      Public Property InputAvaFile As HttpPostedFileBase
  21:   
  22:      <Required(ErrorMessage:="Description is mandatory.")>
  23:      <Display(Name:="Enter description for customer.", Prompt:="Enter description for customer.", Description:="No more than 1000 chars.")>
  24:      <DataType(DataType.MultilineText)>
  25:      <StringLength(1000)>
  26:      Public Property ShortDescription As String
  27:   
  28:      <Required(ErrorMessage:="PublicContacts is mandatory.")>
  29:      <Display(Name:="Enter your public contacts for customer.", Prompt:="Enter your public contacts for customer.", Description:="Any your public contact in free form, No more than 100 chars.")>
  30:      <DataType(DataType.Text)>
  31:      <StringLength(100)>
  32:      Public Property PublicContacts As String
  33:   
  34:      <Display(Name:="Enter your email for Sign in to this site.", Prompt:="Enter your email for Sign in to this site.", Description:="We sent password to this email.")>
  35:      <DataType(DataType.EmailAddress)>
  36:      Public Property AdminContacts As String
  37:   
  38:  End Class

And change the view for this model:


   1:  @ModelType ViewResumeModel
   8:   
   9:  <div class="row">
  10:      @*<form role="form" name="resumeform" id="resumeform" method="post" enctype="multipart/form-data" action="/api/Upload/PostResumeData">*@
  11:      @Using (Html.BeginForm("PostResume", "Resume", FormMethod.Post, New With {.enctype = "multipart/form-data"}))
  12:          @Html.AntiForgeryToken()
  13:          @<div Class="col-md-1 panel1" style="border:none">
  14:          </div>
  15:          @Html.Partial("~/Views/Resume/PostSetSkillPanel.vbhtml")
  16:          @<div class="col-md-7 panel1">
  17:              <h2> Please fill all fields in your public resume </h2>
  18:              <div style="max-height: 750px; min-height:750px; overflow: auto;">
  19:                  <div class="form-group">
  20:                      @*<label for="Title"><span style="color:red">*</span> Title of your bean </label>
  21:                        <input class="form-control" id="title" name="title" placeholder="No more than 100 chars.">*@
  22:                      @Html.LabelFor(Function(m) m.Title)
  23:                      @Html.ValidationMessageFor(Function(m) m.Title, "", New With {.style = "color:red"})
  24:                      @Html.TextBoxFor(Function(m) m.Title, New With {.PlaceHolder = "No more than 100 chars.", .Style = "width:95%;"})
  25:                  </div>
  26:                  <div Class="form-group">
  27:                      @*<label for="InputPDFFile">Upload PDF files with your resume</label>
  28:                        <input type="file" class="form-control-file" id="InputPDFFile" name="InputPDFFile">*@
  29:                      @Html.LabelFor(Function(m) m.InputPDFFile)
  30:                      @Html.TextBoxFor(Function(m) m.InputPDFFile, New With {.type = "file", .Style = "width:95%;"})
  31:                      <p class="help-block">This pdf files not will be parsed or changed.</p>
  32:                  </div>
  33:                  <div class="form-group">
  34:                      @*<label for="InputAvaFile">Upload your Avatar (if necessary)</label>
  35:                        <input type="file" class="form-control-file" id="InputAvaFile" name="InputAvaFile">*@
  36:                      @Html.LabelFor(Function(m) m.InputAvaFile)
  37:                      @Html.TextBoxFor(Function(m) m.InputAvaFile, New With {.type = "file", .Style = "width:95%;"})
  38:                      <p class="help-block">Will be reduced to 100x100 px</p>
  39:                  </div>
  40:                  <div class="form-group">
  41:                      @*<label for="ShortDescription"><span style="color:red">*</span> Enter description for customer </label>
  42:                        <textarea class="form-control" id="ShortDescription" rows="7" placeholder="No more than 1000 chars." name="ShortDescription"></textarea>*@
  43:                      @Html.LabelFor(Function(m) m.ShortDescription)
  44:                      @Html.ValidationMessageFor(Function(m) m.ShortDescription, "", New With {.style = "color:red"})
  45:                      @Html.TextAreaFor(Function(m) m.ShortDescription, New With {.rows = "7", .PlaceHolder = "No more than 1000 chars.", .Style = "width:95%;"})
  46:                  </div>
  47:                  <div class="form-group">
  48:                      @*<label for="PublicContacts"><span style="color:red">*</span> Enter your public contacts for customer </label>
  49:                        <input class="form-control" id="PublicContacts" placeholder="Any your public contact in free form, No more than 100 chars." name="PublicContacts">*@
  50:                      @Html.LabelFor(Function(m) m.PublicContacts)
  51:                      @Html.ValidationMessageFor(Function(m) m.PublicContacts, "", New With {.style = "color:red"})
  52:                      @Html.TextBoxFor(Function(m) m.PublicContacts, New With {.PlaceHolder = "Any your public contact in free form, No more than 100 chars.", .Style = "width:95%;"})
  53:                  </div>
  54:                  <div class="form-group">
  55:                      @*<label for="AdminContacts">Enter your email for Sign in to this site. </label>
  56:                        <input type="email" class="form-control" id="AdminContacts" placeholder="We sent password to this email." name="AdminContacts">*@
  57:                      @Html.LabelFor(Function(m) m.AdminContacts)
  58:                      @Html.ValidationMessageFor(Function(m) m.AdminContacts, "", New With {.style = "color:red"})
  59:                      @Html.TextBoxFor(Function(m) m.AdminContacts, New With {.PlaceHolder = "We sent password to this email.", .Style = "width:200px;"})
  60:                      <span style="color:red">*</span> or <br />
  61:                      <label for="Publiccontacts">Sign In using another account</label>
  62:                      <a class="oauth" alt="Sign in using Github" title="Sign in using Github" href="/script/Membership/OAuthLogOn.aspx?auth=GitHub"><img src="/Images/octicons_github-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  63:                      <a class="oauth" alt="Sign in using Linkedin" title="Sign in using Linkedin" href="/script/Membership/OAuthLogOn.aspx?auth=LinkedIn"><img src="/Images/linkedin-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  64:                      <a class="oauth" alt="Sign in using Facebook" title="Sign in using Facebook" href="/script/Membership/OAuthLogOn.aspx?auth=Facebook"><img src="/Images/facebook-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  65:                      <a class="oauth" alt="Sign in using Google" title="Sign in using Google" href="/script/Membership/OAuthLogOn.aspx?auth=Google"><img src="/Images/google-plus-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  66:                      <a class="oauth" alt="Sign in using Microsoft" title="Sign in using Microsoft" href="/script/Membership/OAuthLogOn.aspx?auth=Microsoft"><img src="/Images/microsoft-lg.png" style="vertical-align:middle;padding-right:3px;border:0;"></a>
  67:                  </div>
  68:                  <button id="PostResume" name="PostResume" type="submit" class="btn btn-primary">Post Resume</button>
  69:                  @Html.ValidationSummary(True, "", New With {.style = "color:red"})
  70:                  <div style="color:red">@ViewBag.Errormessage</div>
  71:              </div>
  72:          </div>
  73:      End Using
  74:      @*</form>*@
  75:  </div>
  76:   
  77:  <script src="~/Scripts/jquery.validate.min.js"></script>
  78:  <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

And after that I have succesfully receive model in MVC comtroller:



5. Custom model provider.

If we have more complex model (you need calculation fields for example or filter it or other prepare) we can opportunity to create own model from simple form fields. Firstly we need prepare special model you need for. In this example I prepare model with name ViewResumeModel2 that has only one difference to model above - instead string in field "skills" it transfer filtered list of string.



Of cource, need to change type of model in controller and view.



My code of special custom model binder is look these.


   1:  Public Class ??ustomModelBinder
   2:      Inherits DefaultModelBinder
   3:   
   4:      Public Overrides Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object
   5:          Select Case bindingContext.ModelType
   6:              Case GetType(ViewResumeModel2)
   7:                  Dim Request As HttpRequestBase = controllerContext.HttpContext.Request
   8:                  Dim SkillArr() As String = Request.Form("skills").Split(":")
   9:                  Return New ViewResumeModel2 With {
  10:                          .Title = Request.Form("Title"),
  11:                          .ShortDescription = Request.Form("ShortDescription"),
  12:                          .PublicContacts = Request.Form("PublicContacts"),
  13:                          .AdminContacts = Request.Form("AdminContacts"),
  14:                          .InputAvaFile = Request.Files("InputAvaFile"),
  15:                          .InputPDFFile = Request.Files("InputPDFFile"),
  16:                          .Skills = (SkillArr.ToList.Where(Function(x) Not String.IsNullOrEmpty(x))).ToList
  17:                  }
  18:              Case Else
  19:                  Return MyBase.BindModel(controllerContext, bindingContext)
  20:          End Select
  21:      End Function
  22:   
  23:  End Class

And in the last step we need to register our custom model bulder on start site procedures.



And this schema working perfectly:



6. Define parameters as raw stream.



Than application/x-www-form-urlencoded stream can be read by the way in line 177 and parsed by the way in line 182.

 170:      Public Async Function CreateDriver(Stream As Stream) As Task(Of Contract.Driver) Implements IDriverService.CreateDriver
 172:   
 173:          If Stream Is Nothing Then
 174:              Throw New WebFaultException(Of String)("MISSING_PARAMETERS", HttpStatusCode.BadRequest)
 175:          End If
 176:   
 177:          Dim Body As String = New StreamReader(Stream).ReadToEnd()
 178:          If String.IsNullOrWhiteSpace(Body) Then
 179:              Throw New WebFaultException(Of String)("MISSING_PARAMETERS", HttpStatusCode.BadRequest)
 180:          End If
 181:   
 182:          Dim Form As NameValueCollection = HttpUtility.ParseQueryString(Body)

Stream also can contains Image or another byte/stream, in this case this is a simplest way to handle it.


 367:      Public Async Function CreateDriverImage(DriverIdPart As String, Stream As Stream) As Task(Of Contract.File) Implements IDriverService.CreateDriverImage
 368:          'Await Federate(Reflection.MethodBase.GetCurrentMethod().Name)
 ...:   
 392:          LocalStorage.WriteFileToDataStore(Root, Location, Stream)

7. Get/Post request to controller from Javascript.


This is controller code.


And this is example of Javascript to create Get/Post request to controller. Script can be attach when form-ready to as @Ajax.BeginForm.



   1:  var did = null;
   2:  var dob = null;
   3:   
   4:  function OnUpdateDriverBegin(xhr)
   5:  {
   6:      var textId = $('#input-driver-id');
   7:      var textFirstName = $('#input-driver-first-name');
   8:      var textLastName = $('#input-driver-last-name');
   9:      var textEmail = $('#input-driver-email');
  10:      var textPhone = $('#input-driver-phone');
  11:      var dropdownStatus = $('#input-driver-status');
  12:   
  13:      var labelStatusMessage = $('#status-message');
  14:      labelStatusMessage.empty();
  15:   
  16:      var id = textId.val().trim();
  17:   
  18:      var firstName = textFirstName.val().trim();
  19:      if (firstName === null || firstName.length <= 0)
  20:      {
  21:          labelStatusMessage.text("Please enter First Name");
  22:          return false;
  23:      }
  24:   
  25:      var lastName = textLastName.val().trim();
  26:      if (lastName === null || lastName.length <= 0)
  27:      {
  28:          labelStatusMessage.text("Please enter Last Name");
  29:          return false;
  30:      }
  31:   
  32:      var email = textEmail.val().trim();
  33:      if (email === null || email.length <= 0)
  34:      {
  35:          labelStatusMessage.text("Please enter Email");
  36:          return false;
  37:      }
  38:   
  39:      var emailRegex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
  40:      if (!emailRegex.test(email))
  41:      {
  42:          labelStatusMessage.text("Please enter valid Email");
  43:          return false;
  44:      }
  45:   
  46:      var phone = textPhone.val().trim();
  47:      if (phone === null || phone.length <= 0)
  48:      {
  49:          labelStatusMessage.text("Please enter Phone");
  50:          return false;
  51:      }
  52:   
  53:      //if (phone.indexOf("+972") !== 0)
  54:      //{
  55:      //    labelStatusMessage.text("Please enter valid Phone");
  56:      //    return false;
  57:      //}
  58:   
  59:      var contentPanel = $('#content-panel');
  60:      var progressPanel = $('#progress-panel');
  61:   
  62:      contentPanel.hide();
  63:      progressPanel.show();
  64:      return true;
  65:  }
  66:   
  67:  function OnUpdateDriverSuccess(data, status, xhr)
  68:  {
  69:      var labelStatusMessage = $('#status-message');
  70:      labelStatusMessage.empty();
  71:   
  72:      if (xhr.status === 200)
  73:      {
  74:          window.location.href = "/Driver";
  75:      }
  76:      else
  77:      {
  78:          labelStatusMessage.text("A temporary error occured");
  79:      }
  80:  }
  81:   
  82:  function OnUpdateDriverFailure(xhr, status, error)
  83:  {
  84:      var contentPanel = $('#content-panel');
  85:      var progressPanel = $('#progress-panel');
  86:   
  87:      contentPanel.show();
  88:      progressPanel.hide();
  89:   
  90:      var labelStatusMessage = $('#status-message');
  91:      switch (xhr.status)
  92:      {
  93:          case 400:
  94:              labelStatusMessage.text("Missing or invalid User Details");
  95:              break;
  96:   
  97:          case 403:
  98:              window.location.href = "/";
  99:              break;
 100:   
 101:          case 500:
 102:          default:
 103:              labelStatusMessage.text("A temporary error occured");
 104:              break;
 105:      }
 106:  }
 107:   
 108:  function DeleteDriver()
 109:  {
 110:      var contentPanel = $('#content-panel');
 111:      var progressPanel = $('#progress-panel');
 112:   
 113:      contentPanel.hide();
 114:      progressPanel.show();
 115:   
 116:      var serviceUrl = '/Service/Driver/Delete/' + did;
 117:   
 118:      $.ajax({
 119:          url: serviceUrl,
 120:          type: 'DELETE',
 121:          async: true,
 122:          cache: false,
 123:          contentType: false,
 124:          processData: false,
 125:          success: function (data, status, xhr)
 126:          {
 127:              var labelStatusMessage = $('#status-message');
 128:              labelStatusMessage.empty();
 129:   
 130:              if (xhr.status === 200)
 131:              {
 132:                  window.location.href = "/Driver";
 133:              }
 134:              else
 135:              {
 136:                  labelStatusMessage.text("A temporary error occured");
 137:              }
 138:          },
 139:          error: function (jqXHR, textStatus, errorThrown)
 140:          {
 141:              progressPanel.hide();
 142:              contentPanel.show();
 143:              switch (jqXHR.status)
 144:              {
 145:                  case 403:
 146:                      window.location.href = "/";
 147:                      break;
 148:   
 149:                  default:
 150:                      $.notify({ message: jqXHR.responseJSON }, { type: 'danger', timer: 2000 });
 151:                      break;
 152:              }
 153:          }
 154:      });
 155:  }
 156:   
 157:  function loadRideTypes()
 158:  {
 159:      var contentPanel = $('#content-panel');
 160:      var progressPanel = $('#progress-panel');
 161:   
 162:      //contentPanel.hide();
 163:      //progressPanel.show();
 164:   
 165:      var serviceUrl = '/Service/RideType';
 166:   
 167:      $.ajax({
 168:          url: serviceUrl,
 169:          type: 'GET',
 170:          async: true,
 171:          cache: false,
 172:          contentType: false,
 173:          processData: false,
 174:          success: function (returnedData)
 175:          {
 176:              var rideTypesJson = returnedData;
 177:   
 178:              var dropdownCarRideType = $('#input-car-ride-type');
 179:   
 180:              var textFirstName = $('#input-driver-first-name');
 181:              var textCarManufacturer = $('#input-car-manufacturer');
 182:   
 183:              var htmlString = "";
 184:              htmlString = htmlString + '<option value="-1" selected="selected">Select Ride Type</option>';
 185:              for (var rideTypeIndex in returnedData)
 186:              {
 187:                  var rideTypeJson = rideTypesJson[rideTypeIndex];
 188:                  var rideTypeId = rideTypeJson['Id'];
 189:                  var rideTypeEName = rideTypeJson['EName'];
 190:                  var rideTypeHName = rideTypeJson['HName'];
 191:                  htmlString += '<option value="' + rideTypeId + '">' + rideTypeHName + '</option>';
 192:              }
 193:              dropdownCarRideType.html(htmlString);
 194:   
 195:              var hasCar = dob['HasCar'];
 196:              var carJson = dob['Car'];
 197:   
 198:              if (hasCar && carJson)
 199:              {
 200:                  var carRideType = carJson['RideTypeId'];
 201:                  dropdownCarRideType.val(carRideType);
 202:              }
 203:   
 204:              progressPanel.hide();
 205:              contentPanel.show();
 206:   
 207:              $(".btn-view-driver-document").click(ViewDriverDocument);
 208:              $(".btn-verify-driver-document").click(VerifyDriverDocument);
 209:   
 210:              textFirstName.focus();
 211:              textCarManufacturer.focus();
 212:          },
 213:          error: function (jqXHR, textStatus, errorThrown)
 214:          {
 215:              progressPanel.hide();
 216:              contentPanel.show();
 217:              switch (jqXHR.status)
 218:              {
 219:                  case 403:
 220:                      window.location.href = "/";
 221:                      break;
 222:   
 223:                  default:
 224:                      $.notify({ message: jqXHR.responseJSON }, { type: 'danger', timer: 2000 });
 225:                      break;
 226:              }
 227:          }
 228:      });
 229:  }
 230:   
 231:  function VerifyDriverDocument(e)
 232:  {
 233:      e.currentTarget.innerHTML = '<i class="fa fa-check"></i>&nbsp;&nbsp;&nbsp;Verifying..';
 234:      $(e.currentTarget).prop('disabled', true);
 235:   
 236:      var serviceUrl = '/Service/Driver/Document/Verify';
 237:   
 238:      $.ajax({
 239:          url: serviceUrl,
 240:          type: 'POST',
 241:          async: true,
 242:          cache: false,
 243:          contentType: false,
 244:          data: $.param({ DocumentIdPart: String(e.currentTarget.id).replace('btn', '') }),
 245:          headers: {
 246:              'Content-Type': 'application/x-www-form-urlencoded'
 247:          },
 248:          processData: false,
 249:          success: function (data, status, xhr)
 250:          {
 251:              if (xhr.status === 200)
 252:              {
 253:                  e.currentTarget.innerHTML = '<i class="fa fa-check"></i>&nbsp;&nbsp;&nbsp;Verified';
 254:                  $(e.currentTarget).prop('disabled', true);
 255:              }
 256:              else
 257:              {
 258:                  e.currentTarget.innerHTML = '<i class="fa fa-check"></i>&nbsp;&nbsp;&nbsp;Verify';
 259:                  $(e.currentTarget).prop('disabled', false);
 260:                  $.notify({ message: jqXHR.responseJSON }, { type: 'danger', timer: 2000 });
 261:              }
 262:          },
 263:          error: function (jqXHR, textStatus, errorThrown)
 264:          {
 265:              switch (jqXHR.status)
 266:              {
 267:                  default:
 268:                      e.currentTarget.innerHTML = '<i class="fa fa-check"></i>&nbsp;&nbsp;&nbsp;Verify';
 269:                      $(e.currentTarget).prop('disabled', false);
 270:                      $.notify({ message: jqXHR.responseJSON }, { type: 'danger', timer: 2000 });
 271:                      break;
 272:              }
 273:          }
 274:      });
 275:  }
 276:   
 277:  function ViewDriverDocument(e)
 278:  {
 279:      //e.stopPropagation();
 280:      //e.stopImmediatePropagation();
 281:      var documentFileId = String(e.currentTarget.id).replace('btn', '');
 282:      var win = window.open('http://api.taxistar.co.il/CoreService.svc/File/' + documentFileId);
 283:      if (win)
 284:      {
 285:          //Browser has allowed it to be opened
 286:          win.focus();
 287:      }
 288:      else
 289:      {
 290:          //Browser has blocked it
 291:          alert('Please allow popups for this website');
 292:      }
 293:  }
 294:   
 295:  function loadDriver()
 296:  {
 297:      var contentPanel = $('#content-panel');
 298:      var progressPanel = $('#progress-panel');
 299:   
 300:      contentPanel.hide();
 301:      progressPanel.show();
 302:   
 303:      var serviceUrl = '/Service/User/View/' + did;
 304:   
 305:      $.ajax({
 306:          url: serviceUrl,
 307:          type: 'GET',
 308:          async: true,
 309:          cache: false,
 310:          contentType: false,
 311:          processData: false,
 312:          success: function (returnedData)
 313:          {
 314:              var userJson = returnedData;
 315:   
 316:              // driver details
 317:              var textId = $('#input-driver-id');
 318:              var imageDriver = $('#input-driver-profile-image');
 319:              var textFirstName = $('#input-driver-first-name');
 320:              var textLastName = $('#input-driver-last-name');
 321:              var textEmail = $('#input-driver-email');
 322:              var textPhone = $('#input-driver-phone');
 323:              var dropdownStatus = $('#input-driver-status');
 324:   
 325:              // car details
 326:              var dropdownCarType = $('#input-car-type');
 327:              var textCarManufacturer = $('#input-car-manufacturer');
 328:              var textCarModel = $('#input-car-model');
 329:              var textCarCapacity = $('#input-car-capacity');
 330:              var textCarColor = $('#input-car-color');
 331:              var textCarRegistration = $('#input-car-registration');
 332:   
 333:              var id = userJson['Id'];
 334:              textId.val(id);
 335:   
 336:              var firstName = userJson['FirstName'];
 337:              textFirstName.val(firstName);
 338:   
 339:              var lastName = userJson['LastName'];
 340:              textLastName.val(lastName);
 341:   
 342:              var status = userJson['Status'];
 343:              dropdownStatus.val(status);
 344:   
 345:              var contactsJson = userJson['Contacts'];
 346:   
 347:              var email = null;
 348:              var phone = null;
 349:   
 350:              for (var contactIndex in contactsJson)
 351:              {
 352:                  var contactJson = contactsJson[contactIndex];
 353:                  if (contactJson['Type'] == 1)
 354:                  {
 355:                      phone = contactJson;
 356:                  }
 357:                  else if (contactJson['Type'] == 2)
 358:                  {
 359:                      email = contactJson;
 360:                  }
 361:              }
 362:   
 363:              var email = email['Value'];
 364:              textEmail.val(email);
 365:   
 366:              var phone = phone['Value'];
 367:              textPhone.val(phone);
 368:   
 369:              var driverProfile = userJson['Profile'];
 370:              if (driverProfile)
 371:              {
 372:                  var driverProfileThumbnail = driverProfile['Thumbnail'];
 373:                  if (driverProfileThumbnail)
 374:                  {
 375:                      imageDriver.attr("src", "http://api.taxistar.co.il/CoreService.svc/File/" + driverProfileThumbnail['Id']);
 376:                  }
 377:              }
 378:   
 379:              var hasCar = userJson['HasCar'];
 380:              var carJson = userJson['Car'];
 381:   
 382:              if (hasCar && carJson)
 383:              {
 384:                  var carManufacturer = carJson['Manufacturer'];
 385:                  textCarManufacturer.val(carManufacturer);
 386:   
 387:                  var carModel = carJson['Model'];
 388:                  textCarModel.val(carModel);
 389:   
 390:                  var carCapacity = carJson['Capacity'];
 391:                  textCarCapacity.val(carCapacity);
 392:   
 393:                  var carColor = carJson['Color'];
 394:                  textCarColor.val(carColor);
 395:   
 396:                  var carRegistration = carJson['RegistrationNumber'];
 397:                  textCarRegistration.val(carRegistration);
 398:   
 399:                  var carType = carJson['Type'];
 400:                  dropdownCarType.val(carType);
 401:              }
 402:   
 403:              var documentsJson = userJson['Documents'];
 404:   
 405:              var htmlString = "";
 406:              for (var documentIndex in documentsJson)
 407:              {
 408:                  var documentJson = documentsJson[documentIndex];
 409:   
 410:                  var documentId = documentJson['Id'];
 411:   
 412:                  var documentType = '';
 413:                  switch (documentJson['Type'])
 414:                  {
 415:                      case 1:
 416:                          documentType = "Driver Licence";
 417:                          break;
 418:   
 419:                      case 2:
 420:                          documentType = "Car Licence";
 421:                          break;
 422:   
 423:                      case 3:
 424:                          documentType = "Car Insurance";
 425:                          break;
 426:   
 427:                      case 4:
 428:                          documentType = "Taxi Licence";
 429:                          break;
 430:                  }
 431:   
 432:                  var documentIdentifier = documentJson['Identifier'];
 433:                  var validFrom = documentJson['ValidityFrom'];
 434:                  var validTo = documentJson['ValidityTo'];
 435:                  var isVerified = documentJson['IsVerified'];
 436:                  var documentFileId = documentJson['File']['Id'];
 437:   
 438:                  //var verified = '';
 439:                  //if (isVerified)
 440:                  //    verified = "Yes";
 441:                  //else
 442:                  //    verified = "No";
 443:   
 444:                  htmlString += '<tr><td>' + documentType + '</td><td>' + documentIdentifier + '</td><td>' + validFrom + '</td><td>' + validTo + '</td>';
 445:   
 446:                  htmlString += '<td><button type="button" class="btn btn-danger btn-round btn-view-driver-document" role="button" id="btn' + documentFileId + '"><i class="fa fa-eye"></i>&nbsp;&nbsp;&nbsp;View</button></td>';
 447:   
 448:                  if (isVerified)
 449:                      htmlString += '<td><button type="button" class="btn btn-danger btn-round btn-verify-driver-document" role="button" id="btn' + documentId + '" disabled="disabled"><i class="fa fa-check"></i>&nbsp;&nbsp;&nbsp;Verified</button></td>';
 450:                  else
 451:                      htmlString += '<td><button type="button" class="btn btn-danger btn-round btn-verify-driver-document" role="button" id="btn' + documentId + '"><i class="fa fa-check"></i>&nbsp;&nbsp;&nbsp;Verify</button></td>';
 452:   
 453:                  htmlString += '</tr>';
 454:              }
 455:   
 456:              var tableBodyDocuments = $('#table-body-documents');
 457:              tableBodyDocuments.html(htmlString);
 458:   
 459:              dob = userJson;
 460:   
 461:              //progressPanel.hide();
 462:              //contentPanel.show();
 463:   
 464:              //textFirstName.focus();
 465:              //textCarManufacturer.focus();
 466:   
 467:              loadRideTypes();
 468:          },
 469:          error: function (jqXHR, textStatus, errorThrown)
 470:          {
 471:              progressPanel.hide();
 472:              contentPanel.show();
 473:              switch (jqXHR.status)
 474:              {
 475:                  case 403:
 476:                      window.location.href = "/";
 477:                      break;
 478:   
 479:                  default:
 480:                      $.notify({ message: jqXHR.responseJSON }, { type: 'danger', timer: 2000 });
 481:                      break;
 482:              }
 483:          }
 484:      });
 485:  }
 486:   
 487:  function documentReady()
 488:  {
 489:      var parts = window.location.href.split('/');
 490:      var lastSegment = parts.pop() || parts.pop();
 491:      did = lastSegment;
 492:   
 493:      var buttonDelete = $('#button-driver-delete-submit');
 494:      if (buttonDelete !== null)
 495:          buttonDelete.click(DeleteDriver);
 496:   
 497:      loadDriver();
 498:  }
 499:   
 500:  $(document).ready(documentReady);

More of this method Inject OnBegin/OnSuccess/OnFailure custom Javascript code into ASP.NET Ajax tag by Bundle of jquery.unobtrusive-ajax.min.js



Comments ( )
Link to this page: //www.vb-net.com/RequestParameters/index.htm
< THANKS ME>