-3

I'm working on Asp.net project. I created a Form, which asks for connectionId and holderFirstName as Input. The name of asp-action is SendProofNameRequest.

In Controller, I wrote a Method SendProofNameRequest which take connectionId and holderFirstName as Parameters. But the problem is, the purpose I'm taking holderFirstName as Input is to use this in another Method (VerifyFirstName).

So, my question is how to take holderFirstName as input from user and use this in another method / VerifyFirstName (not SendProofNameRequest).

Details.cshtml

    <form class="input-group mb-3" asp-controller="Proof" asp-action="SendProofNameRequest">
        <input type="hidden" name="connectionId" value="@Model.Connection.Id" />
        <input type="text" name="holderFirstName" autocomplete="off" class="form-control" placeholder="Enter First Name" aria-label="First Name" aria-describedby="basic-addon2">
        <div class="input-group-append">
            <button class="btn btn-outline-info" type="submit">Request a Proof of First Name</button>
        </div>
    </form> 

ProofController.cs

    [HttpPost]
    public async Task<IActionResult> SendProofNameRequest(string connectionId, out string holderFirstName)
    {
        var agentContext = await _agentProvider.GetContextAsync();
        var connectionRecord = await _walletRecordService.GetAsync<ConnectionRecord>(agentContext.Wallet, connectionId);
        var proofNameRequest = await CreateProofNameMessage(connectionRecord);
        await _messageService.SendAsync(agentContext.Wallet, proofNameRequest, connectionRecord);

        return RedirectToAction("Index");
    }

VerifyFirstName Method

I want to replace firstname (static value) with holderFirstName (dynamic value / user entered in form)

    public bool VerifyFirstName(PartialProof proof)
    {
        var firstName = "Fyodor";
        var name = proof.RequestedProof.RevealedAttributes.First();
        if (name.Value.Raw.Equals(firstName))
        { 
            return true; 
        }

        return false;
    }

UPDATE

As u said to add models, I did that... add the models in ViewModel page and call the @model in View page..

Now, to call the stored values in model in Verify methods controller.

VerifyProof(string proofRecordId) methods calls for another method VerifyFirstName(proof) which does the actual verification.

Kindly have a look at code and can u point out where to add model.HolderFirstName and SendNameRequestViewModel model in which method e.g. VerifyProof(string proofRecordId), VerifyFirstName(proof).. I was getting an errors..

    [HttpGet]
    public async Task<IActionResult> VerifyProof(string proofRecordId, SendNameRequestViewModel model)
    {
        var agentContext = await _agentProvider.GetContextAsync();
        var proofRecord = await _proofService.GetAsync(agentContext, proofRecordId);
        var request = JsonConvert.DeserializeObject<ProofRequest>(proofRecord.RequestJson);
        var proof = JsonConvert.DeserializeObject<PartialProof>(proofRecord.ProofJson);
        bool verified = false;
        switch (request.Name)
        {
            case "ProveYourFirstName":
                verified = VerifyFirstName(proof, model.HolderFirstName); break;
            default:
                    break;
        }
        if (!verified)
        {
            proofRecord.State = ProofState.Rejected;
            await _walletRecordService.UpdateAsync(agentContext.Wallet, proofRecord);
        }

        return RedirectToAction("Index");
    }

    public bool VerifyFirstName(PartialProof proof, SendNameRequestViewModel model.HolderFirstName)
    {
        var firstName = model.HolderFirstName;
        var name = proof.RequestedProof.RevealedAttributes.First();
        if (name.Value.Raw.Equals(firstName))
        { 
            return true; 
        }

        return false;
    }
  • Welcome to StackOverflow. If I understand correctly, you're having issues with how functions work. Just pass the first name as a parameter to your verify method from your SendProof method. You may need to create a second verify method since I'm not sure what PartialProof type is. – HazardousGlitch Jul 17 '20 at 16:25
  • can't do that, asp-action is `SendProofNameRequest`, the name of the method should be also `SendProofNameRequest` –  Jul 17 '20 at 17:45

1 Answers1

1

First of all, the actions/methods in the controller class are meant to handle requests coming from the client to the server. They're not just methods in a class.

Hence I think you need to take out out keyword from the parameter holderFirstName. Or better, to use a view model to pass between the view and the controller:

public class SendNameRequestViewModel
{
    [Required]
    public string ConnectionId { get; set; }

    [Required]
    public string HolderFirstName { get; set; }
}
public class ProofController : Controller
{
    public async Task<IActionResult> SendNameRequest(string connectionId)
    {
        // Initialize the view model if needed, i.e., filling its ConnectionId either
        // from query string or cache. I don't know how you get the connectionId

        var agentContext = await _agentProvider.GetContextAsync();
        var connectionRecord = await _walletRecordService.GetAsync<ConnectionRecord>(agentContext.Wallet, connectionId);
        if (connectionRecord == null)
        {
            return NotFound();
        }

        var vm = new SendNameRequestViewModel
        {
            ConnectionId = connectionId
        };
        return View(vm);
    }
}

Then on the view, you declare its model as SendNameRequestViewModel so that you don't have to hard code the input names/

Notes: I've also added validation summary and validation message for inputs.

@model SendNameRequestViewModel

...

<form class="input-group mb-3" method="post" asp-controller="Proof" asp-action="SendNameRequest">
    <input type="hidden" asp-for="ConnectionId" />

    <div asp-validation-summary="ModelOnly"></div>

    <input asp-for="HolderFirstName" autocomplete="off" class="form-control" 
      placeholder="Enter First Name" aria-label="First Name" aria-describedby="basic-addon2">
    <span asp-validation-for="HolderFirstName" class="text-danger"></span>

    <div class="input-group-append">
        <button class="btn btn-outline-info" type="submit">Request a Proof of First Name</button>
    </div>
</form>

For your VerifyFirstName check, there are so many way to do it. You can directly run its logic in the controller action body, for example. I would create an extension method against PartialProof object:

public static class PartialProofExtensions
{
    public static bool VerifyFirstName(this PartialProof proof, string firstName)
    {
        if (proof == null)
        {
            return false;
        }

        var name = proof.RequestedProof.RevealedAttributes
            .FirstOrDefault();

        return (name != null && name.Value.Raw.Equals(firstName));
    }
}

When the form is posting back, you can just run the validation check in the action method:

[HttpPost]
[ValidateAntiforgeryToken]
public async Task<IActionResult> SendNameRequest(SendNameRequestViewModel model)
{
    if (ModelState.IsValid)
    {
        var agentContext = await _agentProvider.GetContextAsync();
        var connectionRecord = await _walletRecordService.GetAsync<ConnectionRecord>(agentContext.Wallet, model.ConnectionId);
        if (connectionRecord == null)
        {
            ModelState.AddModalError("", "Invalid connection Id.");
            return View(model);
        }

        var proofNameRequest = await CreateProofNameMessage(connectionRecord);
        if (!proofNameRequest.VerifyFirstName(model.HolderFirstName))
        {
            ModelState.AddModalError(nameof(model.HolderFirstName), "Invalid first name.");
            return View(model);
        }

        await _messageService.SendAsync(agentContext.Wallet, proofNameRequest, connectionRecord);

        return RedirectToAction("Index");
    }

    return View(model);
}
David Liang
  • 20,385
  • 6
  • 44
  • 70
  • first thanks for your response.. let me past the code (complete pages), it will be more easy for you to understand my scenario –  Jul 17 '20 at 17:41
  • ProofController.cs -> https://pastebin.fun/HSABpXyrPY ProofsViewModel.cs -> https://pastebin.fun/VLkepDvAkC –  Jul 17 '20 at 17:44
  • it didn't solved because, I want to take input from user in `holderFirstName` in view page, store this in variable and use it in `VerifyFirstName` method. –  Jul 18 '20 at 07:18
  • @MattGreen: so does that mean in the `VerifyFirstName` function, you can't pass the first name as string parameter? – David Liang Jul 18 '20 at 07:49
  • that's my point.. I used `var firstName = "Fyodor";` (static value) as an example, and want to replace this value ("Fyodor") with `holderFirstName` (user input value). –  Jul 18 '20 at 07:56
  • I already tried to use `out` reference, but can't use with async methods -> https://stackoverflow.com/questions/18716928/how-to-write-an-async-method-with-out-parameter –  Jul 18 '20 at 07:57
  • I want to use `string holderFirstName` as parameter in `VerifyFirstName`, which stores the value entered by user in form. –  Jul 18 '20 at 08:35
  • Have you looked at my answer? That's what I exactly did: `if (!proofNameRequest.VerifyFirstName(model.HolderFirstName))`. `model.HolderFirstName` is the input from the user. – David Liang Jul 18 '20 at 17:14
  • yes, I tried this.. but there is one problem and that's why I sent u the code in pastebin, so u can look at complete page.. –  Jul 19 '20 at 12:09
  • in this code -> https://pastebin.fun/HSABpXyrPY, in the bottom `VerifyProof(string proofRecordId)` methods calls for another method `VerifyFirstName(proof)` which does the actual verification... –  Jul 19 '20 at 12:13
  • my question is if you look at the code (in pastebin), can u point out where to add `model.HolderFirstName` and `SendNameRequestViewModel model` in which method e.g. `VerifyProof(string proofRecordId)`, `VerifyFirstName(proof)`.. I was getting errors.. –  Jul 19 '20 at 12:15
  • can u please help? I've been trying but no luck... I updated the code... have a look –  Jul 19 '20 at 16:11
  • I don't know how to help you. I mean I don't know what you're working on. I highly recommend you to take a deep look on the codes I pasted and try to understand how things work. Just by looking at your codes in pastebin, I have no idea what's going on, which actions are GET methods that prepare the view models to the views, which ones are POST methods that take the returned view and process things, because your naming conventions are off, for example, I see `SendProofRequestNameView()` and `SendProofNameRequest()`. I am not sure if they both work on the same view. – David Liang Jul 19 '20 at 16:25
  • thanks for ur time, just have a look at the updated code (in the question section above).. i'm following ur code.. but my last problem is why I'm getting error, when calling a values stored in model in controller page.. now, problem is with verify methods (2, one calls another)... that's it.. –  Jul 19 '20 at 16:30
  • @MattGreen: why did you have the view model as the parameter in a HttpGet method? The view model is supposed to be built in the HttpGet method and return it to the view. Then on the form post, the HttpPost method will capture the view model as the parameter (thanks for the model binding) and you work on your logic to verify, save, etc. – David Liang Jul 19 '20 at 16:37
  • 1
    sorry for can't explaining my point correctly, but thanks for ur time :) –  Jul 19 '20 at 17:06