3

I am trying to perform a search functionality in Asp.net core, this is my controller

[HttpPost("searchbyname")]
   public async Task<ActionResult<List<SelectedChildDto>>> SearchByName([FromBody]string firstName)
   { if (string.IsNullOrWhiteSpace(firstName)) { return new List<SelectedChildDto>(); }
            return await _context.Children
                .Where(x => x.FirstName.Contains(firstName))
                .OrderBy(x => x.FirstName)
                .Select(x => new SelectedChildDto { Cld = x.Cld, ChildCode = x.ChildCode, 
                 FirstName = x.FirstName, PhotoPath = x.PhotoPath })
                .Take(5)
               .ToListAsync();               
              
        }

I have this DTO class from the model

namespace API.Dtos
{
    public class SelectedChildDto
    {
      
        public int Cld { get; set; }

        public string ChildCode { get; set; }
     
        public string FirstName { get; set; }
         public string PhotoPath { get; set; }
    }
}

"errors": { "$": [ "The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1." ] }

King Genius
  • 51
  • 1
  • 1
  • 6

2 Answers2

3

The problem is related to System.Text.Json deserialization of body text for the single [FromBody] string firstName argument of your controller. For example, you need just to send "John" in body instead of full-featured JSON {"firstName": "John"}.

Check also this answer to the similar question.

Vlad Rudenko
  • 2,363
  • 1
  • 24
  • 24
0

I don't know how you pass firstName in your view, but your data format is not correct.

If you just passed a string firstName without [FromBody],You can refer to the following code.

Controller:

 [HttpGet]
 public async Task<IActionResult> SearchByName()
 {
     var children = from m in _context.Children
                       select m;
     return View(await children.ToListAsync());
 }
[HttpPost]
public async Task<ActionResult<List<SelectedChildDto>>> SearchByName(string firstName)
{
    if(string.IsNullOrWhiteSpace(firstName))
    {
        return new List<SelectedChildDto>();
    }
    return await _context.Children
        .Where(x => x.FirstName.Contains(firstName))
        .OrderBy(x => x.FirstName)
        .Select(x => new SelectedChildDto
        {
            Id = x.Id,
            ChildCode = x.ChildCode,
            FirstName = x.FirstName,
            PhotoPath = x.PhotoPath
        })
        .Take(5)
       .ToListAsync();
}

View:

@model IEnumerable<API.Models.SelectedChildDto>
<form asp-controller="Home" asp-action="SearchByName" method="post">
    <p>
        Title:<input type="text" name="firstName"/>
        <input type="submit" value="check"/>
    </p>
</form>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.ChildCode)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.PhotoPath)
            </th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.ChildCode)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PhotoPath)
            </td>
        </tr>
}
    </tbody>
</table>

Test Result: enter image description here enter image description here enter image description here

And if you wish to use [FromBody], you can refer to the following code. Controller:

 [HttpGet]
 public async Task<IActionResult> SearchByName()
 {
     var children = from m in _context.Children
                       select m;
     return View(await children.ToListAsync());
 }
[HttpPost]
public async Task<ActionResult<List<SelectedChildDto>>> SearchByName([FromBody] string firstName)
{
    if(string.IsNullOrWhiteSpace(firstName))
    {
        return new List<SelectedChildDto>();
    }
    return await _context.Children
        .Where(x => x.FirstName.Contains(firstName))
        .OrderBy(x => x.FirstName)
        .Select(x => new SelectedChildDto
        {
            Id = x.Id,
            ChildCode = x.ChildCode,
            FirstName = x.FirstName,
            PhotoPath = x.PhotoPath
        })
        .Take(5)
       .ToListAsync();
}

View:

@model IEnumerable<API.Models.SelectedChildDto>
<p>
        Title:<input type="text" id="firstName" name="firstName"/>
        <button class="btn btn-primary" onclick="Inquire()">check</button>
</p>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.ChildCode)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.PhotoPath)
            </th>
            
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.ChildCode)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PhotoPath)
            </td>
            
        </tr>
}
    </tbody>
</table>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
    function Inquire() 
    {
        $.ajax({
            contentType: 'application/json; charset=utf-8',
            dataType: 'JSON',
            url: '/Home/SearchByName',
            type: "post",
            data: JSON.stringify($("#firstName").val()),
            success: function (result) {
                alert(JSON.stringify(result));
            },
            failure: function (response) {
                console.log(response);
            }
        });
    }
</script>

Test Result: enter image description here enter image description here

Chen
  • 4,499
  • 1
  • 2
  • 9
  • Thank you @Chen for the troubleshooting, actually [FromBody] was use , and I am using angular for the front end, The issue resolved – King Genius May 26 '22 at 14:36