How to add a model in a Razor page from other location - c#

My Model
public class UserRegistrationViewModel
{
public string Description { get; set; }
}
Index
#model UserRegistrationViewModel
<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">
<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>
Perfect up there but what happens if I have my Entity Domains declared in a class library project?
How can I place the address of that class on my razor page?
this sentence is correct? I'm currently making an error
#model DomainEntities.ViewModel.UserRegistrationViewModel
Another Example I'm currently making an error
#model Domain.ViewModel.UserLogInViewModel
#{
ViewBag.Title = "Login";
}
<h2>Login</h2>
<form method="post" asp-controller="Account" asp-action="Login"
asp-route-returnurl="#Model.ReturnUrl">
<div asp-validation-summary="ModelOnly"></div>
<div>
<label asp-for="Username"></label>
<input asp-for="Username" />
<span asp-validation-for="Username"></span>
</div>
<div>
<label asp-for="Password"></label>
<input asp-for="Password" />
<span asp-validation-for="Password"></span>
</div>
<div>
<label asp-for="RememberMe"></label>
<input asp-for="RememberMe" />
<span asp-validation-for="RememberMe"></span>
</div>
<div>
<input type="submit" value="Login" />
</div>
</form>

So if your Web project directly references your DomainEntities project then yes, it will work you just need to specify the full namespace to the ViewModel
#model My.Full.Namespace.DomainEntities.ViewModel.UserRegistrationViewModel
or maybe cleaner:
#using My.Full.Namespace.DomainEntities.ViewModel
#model UserRegistrationViewModel
for the second error, your namespace to the ViewModel is different, ie Domain vs DomainEntities It is likely that your namespaces are incorrect or are not fully spelled out.
If you are using some sort of Dependency Injection to inject your DomainEntities then without some crazy work-arounds your way will not work. The Web needs a direct dependency on the project with your ViewModels.
Finally, I question you putting your ViewModels in a separate project, I would say that for all except the most edge-case scenarios, your ViewModels should be in your Web project.

Related

Form Post with Facebook C# SDK

Can anyone point me in the direction of how I can use a form post with the Facebook C# SDK in an MVC app? It's an iframe based Canvas application.
I have the following code
[HttpPost, CanvasAuthorize(Permissions = "publish_stream")]
public ActionResult Enter(FormCollection col)
{
var fbApp = new FacebookClient(this.CurrentSession.AccessToken);
JsonObject result = (JsonObject)fbApp.Get("me");
long FacebookId = long.Parse(result["id"].ToString());
//CODE TO INSERT GOES HERE
return View();
}
And the form is this
<form action="/EnterComp/Enter" enctype="multipart/form-data" method="post">
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<label for="Text">Text</label>
</div>
<div class="editor-field">
<input id="Text" name="Text" type="text" value="" />
</div>
<div class="editor-label">
<label for="ImagePath">ImagePath</label>
</div>
<div class="editor-field">
<input type="file" name="ImagePath" id="ImagePath">
</div>
<div class="editor-label">
<label for="VideoPath">VideoPath</label>
</div>
<div class="editor-field">
<input type="file" name="VideoPath" id="VideoPath">
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
</form>
But everytime I submit the form, it appears to re-authenticate - and thus lose the form collection. Now I'm sure there's something really simple I'm missing, any help would be appreciated.
EDIT
I think I've answered my own question here, but in case anyone else after me looks. The solution, for me at least, was here.
However, if anyone can suggest anything else. Please help!
There is actually a helper for MVC forms that will fix this issue for you.
The helper goes inside your form:
Razor Syntax:
#Html.FacebookSignedRequest();
ASP.NET Syntax
<%=Html.FacebookSignedRequest() %>
All this actually does is store your signed_requeset as a hidden on your form. This way when the form is posted the Facebook authenticator will be able to reauthorize the request.

Form not posting nor calling controller method

I have a simple html form
<h1>Create Make</h1>
<form id="form1" method="post" action="api/SampleData/CreateMake"
enctype="application/x-www-form-urlencoded">
<div>
<label for="id">Id</label>
</div>
<div>
<input name="id" type="text" />
</div>
<div>
<label for="name">Name</label>
</div>
<div>
<input name="name" type="text" />
</div>
<div>
<label for="abrv">Abrv</label>
</div>
<div>
<input name="abrv" type="text" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
From my understanding, if the names are correct (which they should be) that information should be automagically converted into an object and on button press it should call the CreateMake method in the controller.
This is the controller method
[ActionName("CreateMake")]
[HttpPost]
public IActionResult CreateMake(VehicleDto vehicle)
{
_vehicleService.InsertMake(vehicle);
return Ok(vehicle);
}
It should take the object and run the insert method, right?
Nothing is being done on button press though, checked console and network on chrome, nothing. Controller method isn't being called either.
Controller does have a route
[Route("api/[controller]")]
public class SampleDataController : Controller
SOLVED:
You need to use <form ngNoForm> if you want to use native form submission in angular
Your action attribute looks suspicious.
action="api/SampleData/CreateMake"
That would mean the form will post its data to a path named "api/Sampledata/Createmake" underneath the current page's URL.
Try this root relative action:
action="/api/SampleData/CreateMake"
Instead of using a form with a post action maybe incorporate HTML Helpers. You can convert an Action Link to a Button by using bootstrap:
#Html.ActionLink("Submit", "CreateMake", "SampleData", null, new { #class = "btn btn-primary btn-large" })
You could even use a URL Action within a button to specify the correct route
<input type="submit" value="Submit" onclick="location.href=' Url.Action("CreateMake", "SampleData")'" />
This should ensure that the controller method is called.
Also, not part of the question but as a recommendation I would suggest using more HTML Helpers in general. It is considered best practise when using MVC and it makes your code much more readable and understandable. For example:
using (Html.BeginForm())
{
<label for="id">ID:</label>
Html.TextBox("ID")
//other componants
<input type="submit" value="Submit" />
}
I hope this helps and that you can solve the problem, have a lovely day.

Submiting Ajax form in Net .Core

I created wizard with the jQuery-Steps lib with simple form for now. There is no Submit button. I submit form on finish step via jQuery.
I am already using jQuery calls all over the place, and I have included all scripts, and I needed form for uploading images and other stuff, it's easier with it.
Nothing happens, the controller action is not called.
I just getting redirected on start page with all this parameters in query string.
Like this:
https://localhost:44380/Dashboard?Name=Aaaa&Surename=Bbbb&City=Cccc
Dashboard is all made with Ajax and partial views. And from person option in menu I'm getting redirected on home view in Dashboard with all this parameters.
This is the form:
<form asp-controller="PersonSettings" asp-action="SaveForm" data-ajax="true" data-ajax-method="POST" id="personForm" class="steps-validation wizard-notification">
<!-- Step 1 -->
<h6>Person</h6>
<fieldset>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="Name">
Person Name :
<span class="danger">*</span>
</label>
<input autocomplete="off" type="text" class="form-control required" id="Name" name="Name">
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label for="Surname">
Person Surname:
<span class="danger">*</span>
</label>
<input autocomplete="off" type="url" class="form-control required" id="Surname" name="Surname">
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<label for="City">
Person City:
<span class="danger">*</span>
</label>
<input autocomplete="off" type="url" class="form-control required" id="City" name="City">
</div>
</div>
</div>
</fieldset>
</form>
This is the Model:
public class PersonDto {
public string Name { get; set; }
public string Surname { get; set; }
public string City { get; set; }
}
Here is Action in PersonSettings controller:
[Route("SaveForm")]
[HttpPost]
public IActionResult SaveForm(PersonDto Person) {
//Do something with person model
return Ok();
}
And on finish button I have jQuery submit called on this form:
$('#personForm').submit();
EDIT:
I tried with this parameters:
<form action="PersonSettings/SaveForm" method="post" id="personFrom" class="steps-validation wizard-notification">
And this works.. it's good, but why does the first method not work? Because I need this in Ajax and finish method.
I didn't find any way to post image with form with classic Ajax call. Because I can't read image path (it's not exposed to the browsers).
I think that you didn't installed Tag Helpers. If it works with action attribute, it should work with Tag Helpers attribute. Because you're using Asp-Net-Controller attribute.
https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.TagHelpers
Please let me know.

ASP.NET Core redirecting to the same page after submitting a form with HttpPost method

I am developing a web application using ASP.NET Core 2.0.
First of all i have a main view called NewOrder.cshtml:
#using Microsoft.AspNetCore.Mvc.Rendering
#using MokaKukaMap.Orders.ViewModels.Models
#model MokaKukaMap.Orders.ViewModels.Models.NewOrderViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.Partial("_NewOrder")
In this main view I use a form in a partial view (_NewOrder.cshtml):
<form asp-controller="NewOrder" asp-action="CreateOrder" class="well">
<div id="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" id="eventID" class="form-control">
<div class="form-group">
<label asp-for="Address" class=""></label>
<div class="">
<input asp-for="Address" class="form-control">
<span asp-validation-for="Address" class="text-danger"> </span>
</div>
</div>
<div class="form-group">
<label asp-for="PhoneNumber" class=""></label>
<div class="">
<input asp-for="PhoneNumber" class="form-control">
<span asp-validation-for="PhoneNumber" class="text-danger"> </span>
</div>
</div>
</div>
<div id="ErrorsBox" class="alert alert-danger" style="display: none;"></div>
<div class="form-group">
<div class="">
<input type="submit" formnovalidate="formnovalidate" value="Submit new order" class="btn btn-primary" />
</div>
</div>
</form>
And of course I have the corresponding controller and HttpPost action method, which is the following:
public class NewOrderController : Controller
{
private readonly INewOrderSaverRequestHandler _newOrderSaverRequestHandler;
public NewOrderController(INewOrderSaverRequestHandler newOrderSaverRequestHandler)
{
_newOrderSaverRequestHandler = newOrderSaverRequestHandler;
}
public IActionResult NewOrder()
{
return View();
}
[HttpPost]
public IActionResult CreateNewOrder(NewOrderViewModel newOrder)
{
_newOrderSaverRequestHandler.Handle(newOrder, ModelState);
return RedirectToPage("NewOrder");
}
}
The issue is that if I click on the submit button, the page is redirected to the following url: "http://localhost:13078/NewOrder/CreateOrder". But what I would like is to stay on the same page, so at "http://localhost:13078/NewOrder/NewOrder" url
I have already tried some solutions which I've found here at stackoverflow:
Using return RedirectPage("NewOrder") - with this I am still redirected to .../NewOrder/CreateOrder so to an 404 error page. Furthermore I tried to use it with other cobinations like return RedirectPage("/") or return RedirectPage("NewOrder/NewOrder") but none of them led to the correct solution
With return View("NewOrder") i am still directed to ".../NewOrder/CreateOrde" as well
I also tried the following: return Page() but this dependency/reference is unknown in asp.net core 2.0.
Furthermore i tried to solve my issue with setting the "asp-route-returnurl" attribute in my html form tag, but no success with it.
Well, I think that maybe my issue has something to do with my routing. I use the following routing-setting in my Startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Map}/{action=Index}/{id?}");
});
Last but not least I tried to use annotation routing, but it could also not solve my issue:
[Route("[controller]/NewOrder")]
[HttpPost]
public IActionResult CreateNewOrder(NewOrderViewModel newOrder)
{
_newOrderSaverRequestHandler.Handle(newOrder, ModelState);
return RedirectToPage("NewOrder");
}
So what I want is that after clicking the submit button, create a new order (which is handled by INewOrderSaverRequestHandler) then stay on the same page. What do you think, where the problem lies in my code? Thanks in advance!
please replace this
<form asp-controller="NewOrder" asp-action="CreateOrder" class="well">
with
<form asp-controller="NewOrder" asp-action="NewOrder" class="well">
you are using asp-action="CreateOrder" thats why it is going to CreateOrder methode

MVC Posting Form with Partial views returns Null Model

I've been reading multiple posts with this same issue and it seems the consensus is to use sub-model objects along with Editor Templates. I've not refactored my code to do this and I'm still getting a null model returned on post. I can't figure out where I'm going wrong. Here's my proof of concept code:
Controller:
[HttpPost]
public ActionResult CreateNewMatter(NewMatterModel model)
{
WorkflowRepository repo = new WorkflowRepository();
repo.SaveNewMatterWorkflow(model.NewMatterIndex.ClientCode, model.NewMatterIndex.ClientName, model.NewMatterIndex.MatterCode, model.NewMatterIndex.MatterName);
return View();
}
Main View:
#model NBI_Flow.Web.Models.ActionModels.NewMatterModel
#{
ViewBag.Title = "Create New Matter";
}
<div class="screen-container">
#using (Html.BeginForm("CreateNewMatter", "Action", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="top-control-panel">
<div id="button-row">
<input type="button" id="home-button" value="Home" onclick="location.href = '#Url.Action("Index", "Home")'; return false;" />
<input type="submit" id="save-button" value="Save" />
<input type="button" id="delete-button" value="Delete" onclick="location.href = '#Url.Action("Index", "Home")'; return false;" />
<input type="button" id="submit-button" value="Submit" onclick="saveNewMatter();" />
</div>
<div id="status-row">
<div class="status-block">
<label><span>Request Number:</span>013603</label><br />
<label><span>Request Status:</span>01. Draft</label><br />
<label><span>Client #:</span>27619</label>
</div>
<div class="status-block">
<label><span>Request Type:</span>Existing Client</label><br />
<label><span>Created On:</span>02/29/2016 09:43:10 AM</label><br />
<label><span>Client Name:</span>Greenfield Partner LLC</label>
</div>
<div class="status-block">
<label><span>Primary Billing Partner:</span></label><br />
<label><span>Created By:</span>Brian Legg</label><br />
<label><span>BABAC Partner:</span></label>
</div>
</div>
</div>
#Html.Hidden("SuccessUrl", Url.Action("Index", "Home"))
<div id="new-matter-container">
<ul>
<li>Intro</li>
<li>Matter Details</li>
<li>BABAC</li>
<li id="tab3tab">Client Relationship</li>
<li>Risk Management</li>
<li>Relevant Parties/Conflicts</li>
<li>Attachments</li>
<li>Comments</li>
<li>Audit</li>
<li>Copy Request</li>
<li>Proxies</li>
</ul>
<div id="tab0">
#Html.EditorFor(model => model.NewMatterIndex)
</div>
<div id="tab1">
#Html.Partial("_MatterDetails")
</div>
<div id="tab2">
#Html.Partial("_BABAC")
</div>
<div id="tab3">
#Html.Partial("_ClientRelationship")
</div>
<div id="tab4">
#Html.Partial("_RiskManagement")
</div>
<div id="tab5">
#Html.Partial("_RelevantParties")
</div>
<div id="tab6">
#Html.Partial("_Attachments")
</div>
<div id="tab7">
#Html.Partial("_Comments")
</div>
<div id="tab8">
#Html.Partial("_Audit")
</div>
<div id="tab9">
#Html.Partial("_CopyRequest")
</div>
<div id="tab10">
#Html.Partial("_Proxies")
</div>
</div>
}
</div>
I know there are a lot of partials there, but I'm only concerned with that first EditorFor. Once it works I will convert the rest to EditorTemplates.
EditorTemplate (partial):
#model NBI_Flow.Web.Models.ActionModels.NewMatterIndex
<div id="intro-section">
<label>Requesting Attorney:</label>
<select id="attorney-list">
<option value="0">Select...</option>
<option value="1">Abramowitz, Laurie</option>
<option value="2">Adivari, Heather</option>
<option value="3">Adler, Sara</option>
<option value="4">Ainsztein, Zachary</option>
<option value="5">Allardyce, Aaron L</option>
<option value="6">Alten, Klaus</option>
<option value="7">Alvarado, Daniela</option>
<option value="8">Alyonycheva, Tatiana N</option>
</select>
<br /><br />
<label>Please enter the matter name:</label>
<input type="text" id="matterName" />
<br /><br />
#* 100% throw away code *#
<label>Please enter the client code:</label>
#*<input type="text" id="clientCode" />*#
#Html.TextBoxFor(m => Model.ClientCode)
..........
It's the "Model.ClientCode" which I am trying to get to post. When I click the submit button my posted model looks like this:
Any help is greatly appreciated. Let me know if I've left out some important piece of data. Thank you!
Using an editor template is never a requirement. I'm not sure where you're getting that advice, but it should be taken with a grain of salt. The heart of the matter boils down to the name attribute assigned to your input/select/etc. element and what the modelbinder expects that name to be on POST.
For your example here, to bind ClientCode, the modelbinder expects a post value with the name of NewMatterIndex.ClientCode. If it's anything else, just ClientCode for example, then the modelbinder will discard the value.
Now, when dealing with partials (which editor templates are a form of), it's all about context. In a partial, the context is the model for that partial and, importantly, not the model for the main view. So, for example, if you pass Model.NewMatterIndex into a partial as the model, then that is now all the context Razor has when rendering that partial. As a result, if you then do something like:
#Html.EditorFor(m => m.ClientCode)
Inside that partial, the resulting name attribute will be just ClientCode, not NewMatterIndex.ClientCode as it needs to be.
Editor templates are a partial solution only in the respect that EditorFor maintains some of the parent context. When you call something like:
#Html.EditorFor(m => m.NewMatterIndex)
It will properly prefix each of the inputs rendered inside with NewMatterIndex.. That's no guarantee that the names will always be correct, as there could be other issues. However, in this one specific scenario, it would fix the issue. The reason you're still having issues, is likely due to a typo in your editor template. You have:
#Html.EditorFor(m => Model.ClientCode)
Whereas that should be:
#Html.EditorFor(m => m.ClientCode)
They look similar, but actually mean very different things. Also, while your question resolves around this one particular property, it seems that you're both manually creating the HTML for all other inputs and not assigning any of them name attributes. Without a name, the value will not even be posted, let alone bound to anything.

Resources