ASP.NET MVC - URL Action Path - asp.net-mvc

I am writing an app using ASP.NET MVC. I'm in a view that is located at:/orders/{orderId}. That view renders just fine. Inside of it though, I have a button inside of a form that looks like this:
<form action="/orders/{orderId}/flag" method="post">
<button type="submit" class="btn">Flag</button>
</form>
In my controller, I have the following:
public class OrdersController : Controller
{
public ActionResult Details(string id)
{
var model = Orders.FindById(id);
return View(model);
}
public ActionResult Flag(string id)
{
var model = Orders.FindById(id);
model.Flag();
return RedirectToAction(
}
}
My question is, how do I use the ASP.NET MVC helpers to generate the path to my flag action? The action in my form is just a template at the moment which won't work. How do I address this scenario in my razor view?
Thanks!

#Url.Action("Flag", "Orders", new { id = [orderid here] })
I recommend using T4MVC, the you can do:
#Url.Action(MVC.Orders.Flag([orderid here])

Related

Object reference not set to an instance of an object in MVC5

I have an MVC5 app, and in the HomeController, I have an ActionResult defined like this:
public ActionResult BlogRSS()
{
var model = new BlogModel();
string strFeed = "http://webmysite.com/feed";
using (XmlReader reader = XmlReader.Create(strFeed))
{
SyndicationFeed rssData = SyndicationFeed.Load(reader);
model.BlogFeed = rssData;
}
return View(model);
}
Then, for this ActionResult, I created a partial view named BlogRSS, which looks like this:
#model MyApp.Models.BlogModel
#{
if (Model.BlogFeed != null)
{
<ul>
#foreach (var post in Model.BlogFeed.Items.ToList().Take(3))
{
<li><a href='#post.Links.First().Uri' target='_blank'>#post.Title.Text</a></li>
}
</ul>
}
}
And my model is defined simply like this:
public class BlogModel
{
public SyndicationFeed BlogFeed { get; set; }
}
So, the point is that I want to call that partial view in my _Layout.cshtml file, but when the website opens I get the error message specified in the title. I guess it is not calling my BlogRSS method at all. I'm calling it in the _Layout.cshtml like this:
<div class="col-md-4">
Blog
<br />
#Html.Partial("BlogRSS")
</div>
How can I solve the problem, and make sure that the corresponding ActionResult is also called before rendering the View?
The problem is that you're putting a call to a partial view which just renders the view without calling the controller and the model passed to that view is null.
There are couple ways how to fix this:
1) use Action instead of Partial
#Html.Action("BlogRSS", "Blog")
2) Define a base ViewModel which you will pass to the each view and put your feed into it.

Using webforms in MVC

I am learning MVC, following THIS tutorial. (link will take you directly to where i'm stuck). so far I have learnt, there's a controller for every view. Now i have to take input from user through web entry form as mentioned in tutorial. In my project, i have a controller named Default1 and i can run it as localhost:xyz/Default1/Index. it runs perfect.
Then i created a new Controller, named Default2 and bound it to some view to display some data, and it worked perfect as localhost:xyz/Default2/Displaycustomer. the customer information was static (hard coded). and controller is as:
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = "12";
cobj.Name = "Zeeshan";
cobj.Amount = 7000;
return View("DisplayCustomers",cobj);
}
Now i have to take input from User, regarding cutomer iformation, using html page as mentioned in tutorial. so i tried adding a new webform under view folder, and and modified my controller as:
[HttpPost]
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = Request.Form["Id"].ToString();
cobj.Name = Request.Form["Name"].ToString();
cobj.Amount = Convert.ToDouble(Request.Form["Amount"].ToString());
return View("DisplayCustomers",cobj);
}
My Question is: How can i make my project stared, so that it takes input first, and then displays it, using above controller? Did i add the webform at right location? What would be the link to run it? i tried localhost:xyz/Default2/entryform etc. but failed.
(in my entryform.aspx, i have mentioned form action="DisplayCustomer" )
It sounds like what you're missing is an action to just display the form. In otherwords, you just need an action to display a form. That form's POST action should reference your controller's DisplayCustomers action.
So in your controller code:
public class CustomerController : Controller
{
[HttpGet]
public ViewResult New()
{
return View("NewCustomer"); //Our view that contains the new customer form.
}
// Add your code for displaying customers below
}
And in your view, you have code like this
#using(Html.BeginForm("DisplayCustomers", "Customer")) {
<!-- Add your form controls here -->
}
Notice that I'm using the version of the BeginForm helper that specifies the action method and controller to call. This will write the form tag to post back to your DisplayCustomers action. Here is the equivalent HTML:
<form method="POST" action="/Customer/DisplayCustomers">
You would then access your form using the URL http://test.server/Customer/New.
This may not be the best example in the world...but this will at least get you rolling..
url would be:localhost:1234/Home/Customer
the controller
public ActionResult Customer()
{
return View();
}
[HttpPost]
public ActionResult Customer(FormCollection frm)
{
var name = frm["name"].ToString();
var address = frm["address"].ToString();
ViewBag.Name = name;
ViewBag.Address = address;
return View();
}
The view
<div>
#using (Html.BeginForm())
{
<input type="text" name="name" id="name" />
<input type="text" name="address" id="address"/>
<input type="submit" name="submit" value="submit" />
<input type="text" name="namedisplay" value='#ViewBag.Name'/>
<input type="text" name="addressdisplay" value='#ViewBag.Address'/>
}
</div>

Create a folder with a name typed by user in textbox ASP.NET MVC 4 Razor

I'm new to ASP.NET MVC 4.
I'm able to create a folder with a hardcoded name using Directory.CreateDirectory(#"C:/") in my controller, but what I need to do is have the user type the desired folder name into a textbox, and pass that information to the CreateFolder method in the Controller.
Here's the method:
public ActionResult CreateFolder(String newFolderName)
{
Directory.CreateDirectory(#"C:\..." + newFolderName);
return View();
}
In my view I need a textbox for the user to define the desired folder name, and a button that creates the folder with the selected name.
How should I handle this?
I've tried some suggestions from the web, but can't seem to get it going.
View:
#using Folder
#using ( #Html.BeginForm( "CreateFolder", "ControllerName", FormMethod.Post) )
{
#Html.TextBoxFor(x=>x.FolderName)
<input type="submit" id="btnCreateFolder" value="Create Folder" />
}
Model:
public class Folder
{
// other properties
string FolderName {get;set;}
}
Controller:
[HttpPost]
public ActionResult CreateFolder(Folder model)
{
Directory.CreateDirectory(#"C:\..." + model.FolderName);
return View();
}

How to get main controller and action names from partial view action

I have a controller:
public class LanguageController : Controller
{
[HttpGet]
public ActionResult Index()
{
// populate viewModel from database
return PartialView(viewModel)
}
[HttpPost]
public ActionResult Index(string language)
{
LanguageCookie.Write(Response, language);
return RedirectToAction(ACTION, CONTROLLER, new {culture = language});
}
}
and its partial view:
#model MyModel
#using (Html.BeginForm("Index", "Language"))
{
#Html.DropDownList(
Model.SelectedLanguageShortName,
Model.AllLanguages
)
<input type="submit" value="Select" />
}
which I render in _Layout.cshtml:
<div>
#Html.Action("Index", "Language")
</div>
Please let me know how can I get ACTION/CONTROLLER names of main (not partial) controller, from my LanguageController was called. I need this information on the postback where I set cookie and want to redirect user on the same page but with prefered language.
I have found this example:
var rd = ControllerContext.ParentActionViewContext.RouteData;
var currentAction = rd.GetRequiredString("action");
var currentController = rd.GetRequiredString("controller");
But ControllerContext.ParentActionViewContext is null in the postback. I am able to get what I need in the view but it is ugly:
#Html.Hidden("Controller", HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString());
#Html.Hidden("Action", HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString());
How to get the same information in the controller scope?
When Index(string language) is processed ParentActionViewContext is null because this is another request to server and it doesn't know anything about previous request that invoked child action.
Instead of storing control and action in hidden field you can store the whole address and invoke Redirect:
#model MyModel
#using (Html.BeginForm("Index", "Language", new { redirectUrl = Request.Url }))
{
#Html.DropDownList(
Model.SelectedLanguageShortName,
Model.AllLanguages
)
<input type="submit" value="Select" />
}
and then
[HttpPost]
public ActionResult Index(string language, string redirectTo)
{
LanguageCookie.Write(Response, language);
return Redirect(redirectTo);
}
Another way is to save CONTROLER and ACTION in TempData, but in this way you can have problem if somebody open multiple pages of your site.
Third solution is to invoke that method with Ajax and when response arrive reload the page with javascript.

ASP.NET MVC partial view and form action name

How do I create a partial view that has a form with assigned id?
I got as far as:
using (Html.BeginForm(?action?,"Candidate",FormMethod.Post,new {id="blah"}))
Partial view is used for both Create and Edit so first parameter ?action? will be different. I can't figure out what value of ?action? supposed to be.
UPDATE:
I guess I was not clear enough with the question. What I ended up doing is splitting Request.RawUrl to get controller name and action name:
string[] actionUrlParts = ViewContext.HttpContext.Request.RawUrl.Split('/');
using (Html.BeginForm(actionUrlParts.Length >= 2? actionUrlParts[2] : "",
actionUrlParts.Length >= 1 ? actionUrlParts[1] : "", FormMethod.Post, new { id = "blah" }))
Kind of ugly but it works. Is there a better way to get an action name inside the partial view?
Pass in the action to be performed via ViewData.
In your action that renders the view, create a ViewData item for the postback action. In your form reference this ViewData item to fill in the action parameter. Alternatively, you can create a view-only model that includes the action and the actual model as properties and reference it from there.
Example using ViewData:
using (Html.BeginForm( (string)ViewData["PostBackAction"], "Candidate", ...
Rendering actions:
public ActionResult Create()
{
ViewData["PostBackAction"] = "New";
...
}
public ActionResult Edit( int id )
{
ViewData["PostBackAction'] = "Update";
...
}
Example using Model
public class UpdateModel
{
public string Action {get; set;}
public Candidate CandidateModel { get; set; }
}
using (Html.BeginForm( Model.Action, "Candidate", ...
Rendering actions:
public ActionResult Create()
{
var model = new UpdateModel { Action = "New" };
...
return View(model);
}
public ActionResult Edit( int id )
{
var model = new UpdateModel { Action = "Update" };
model.CandidateModel = ...find corresponding model from id...
return View(model);
}
EDIT: Based on your comment, if you feel that this should be done in the view (though I disagree), you could try some logic based off the ViewContext.RouteData
<%
var action = "Create";
if (this.ViewContext.RouteData.Values["action"] == "Edit")
{
action = "Update";
}
using (Html.BeginForm( action, "Candidate", ...
{
%>
Pass nulls as action and controller. Extension will use just current action and current controller
using (Html.BeginForm(null, null, FormMethod.Post, new { id="Model" }))
Action generated for form will be the same as parent view of this partial view.
It generates
<form action="/Orders/Edit/1" id="Model" method="post">
for url http://localhost:1214/Orders/Edit/1
... and this
<form action="/Orders/Create" id="Model" method="post">
for url http://localhost:1214/Orders/Create
<% html.RenderPartial("MyUserControl", Model.ID) %>

Resources