I am working with an MVC project. And I use the application cache to store my whole page to the cache so that the application is still available even offline.
This is my Offline Controller
public class OfflineController : Controller
{
//
// GET: /Offline/
public ActionResult Index()
{
var manifestResult = new ManifestResult("1.0")
{
CacheResources = new List<string>()
{
Url.Action("Index", "Home"),
BundleTable.Bundles.ResolveBundleUrl("~/Content/css", true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/modernizr", true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/jquery",true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/jqueryui", true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/jqueryval",true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/modernizr",true),
BundleTable.Bundles.ResolveBundleUrl("~/Content/css",true),
BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")
},
NetworkResources = new string[] { "*" },
FallbackResources = { { "Images/offline.jpg", "Images/offline.jpg" } }
};
return manifestResult;
}
}
My Home Controller is this
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
This is my class that generate the manifest file
public class ManifestResult : FileResult
{
public ManifestResult(string version)
: base("text/cache-manifest")
{
Version = version;
CacheResources = new List<string>();
NetworkResources = new List<string>();
FallbackResources = new Dictionary<string, string>();
}
public string Version { get; set; }
public IEnumerable<string> CacheResources { get; set; }
public IEnumerable<string> NetworkResources { get; set; }
public Dictionary<string, string> FallbackResources { get; set; }
protected override void WriteFile(HttpResponseBase response)
{
WriteManifestHeader(response);
WriteCacheResources(response);
WriteNetwork(response);
WriteFallback(response);
}
private void WriteManifestHeader(HttpResponseBase response)
{
response.Output.WriteLine("CACHE MANIFEST");
response.Output.WriteLine("#V" + Version ?? string.Empty);
}
private void WriteCacheResources(HttpResponseBase response)
{
response.Output.WriteLine("CACHE:");
foreach (var cacheResource in CacheResources)
response.Output.WriteLine(cacheResource);
}
private void WriteNetwork(HttpResponseBase response)
{
response.Output.WriteLine();
response.Output.WriteLine("NETWORK:");
foreach (var networkResource in NetworkResources)
response.Output.WriteLine(networkResource);
}
private void WriteFallback(HttpResponseBase response)
{
response.Output.WriteLine();
response.Output.WriteLine("FALLBACK:");
foreach (var fallbackResource in FallbackResources)
response.Output.WriteLine(fallbackResource.Key + " " + fallbackResource.Value);
}
}
Here is the error that I encounter
Before I answer, for those of you that just landed here, this is the implementation/article being referenced:
http://www.infoq.com/articles/Offline-Web-Apps
I was able to get this working just fine. One difference between your implementation and mine is that you are listing your manifest as such in the HTML tag:
<html manifest="/Offline">
.. or so I'm guessing.. you didn't post your HTML. I am not sure that HTML tag will be properly interpreted. Here is what I am using and works fine:
<html manifest="/Mobile/Manifest">
My guess is that "Application Cache Error event: Manifest fetch failed (-1)" is the equivalent of a 404.
Hope this helps... I see it's been quite a while since you posted.
I encountered the same issue of the css and script resources not loading in offline mode, when using the same infoq blog post as an example. I resolved the issue by adding the script and css resources using Scripts.Url instead of BundleTable.Bundles.ResolveBundleUrl.
My solution is based on a blog post by Eoin Clayton.
Using the Offline controller code you posted as a base, it may work if you modify it to look as follows:
public class OfflineController : Controller
{
//
// GET: /Offline/
public ActionResult Index()
{
var manifestResult = new ManifestResult("1.0")
{
CacheResources = new List<string>()
{
Url.Action("Index", "Home"),
Scripts.Url("~/bundles/jquery").ToString(),
Scripts.Url("~/bundles/modernizr").ToString(),
Scripts.Url("~/bundles/bootstrap").ToString(),
Scripts.Url("~/Content/css").ToString()
},
NetworkResources = new string[] { "*" },
FallbackResources = { { "Images/offline.jpg", "Images/offline.jpg" } }
};
return manifestResult;
}
}
Hope this helps.
Related
This question may sound trivial, but to me is complicated. I have created a table that stores user's log-in/out date and time. So in my MVC site, I need to be able to insert a new row when the user logs-in and update the row when user clicks on x button or navigates away, etc.
I did a bit of research on "void Session_Start(object sender, EventArgs e)" and thought that might be my solution. However, when I run my site in debug mode in VS, even when I log-out and log-in as another user to the site, the method doesnt get called. Am i missing something, or Session_Start is used for a different purpose?
Any help would be hugely appreciated.
Example:
//Model
{
public class LoginHistory
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public DateTime LoginTime { get; set; }
public DateTime? LogoutTime { get; set; }
[StringLength(128)]
public string UsertId { get; set; }
}
//Controller
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
//............
switch (result)
{
case SignInStatus.Success:
LoginTime(model.UserName);
return RedirectToLocal(returnUrl);
//...........
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
//...............................
LogOutTime(User.Identity.GetUserId());
//...............................
return RedirectToAction("Index", "Home");
}
public void LoginTime(string userName)
{
using (var db = new Applicationdbcontext())
{
var user = db.user.Find(u => u.UserName == userName);
var model = new LoginHistory
{
UserId = user.Id,
LoginTime = DateTime.UtcNow
LogoutTime = null,
};
db.loginhistory.Add(model);
db.SaveChanges();
}
public void LogOutTime(string userId)
{
using (var db = new Applicationdbcontext())
{
var model = db.loginhistory.Where(u => u.Uid == userId).OrderByDescending(u => u.Id).First();
model.LogoutTime = DateTime.UtcNow;
_login.SaveChanges();
}
}
<script type='text/javascript'>
var inFormOrLink;
$('a').on('click', function() { inFormOrLink = true; });
$('form').on('submit', function() { inFormOrLink = true; });
$(window).on("beforeunload", function() {
if(!inFormOrLink){
document.getElementById('logoutForm').submit();
}
})
add this script in your layout page.
I always follow this example. Hopefully it's help for you.
EDITED:
I have Created CRUD Functions for each Modals and now i am trying to get recent Inserted Id and use it in different view.
Here is what I have tried so far
I have created 2 classes(Layer based) for CRUD function for each ContextEntities db to practice pure OOP recursive approach and following is the code.
1. Access Layer
ViolatorDB
public class ViolatorDB
{
private TPCAEntities db;
public ViolatorDB()
{
db = new TPCAEntities();
}
public IEnumerable<tbl_Violator> GetALL()
{
return db.tbl_Violator.ToList();
}
public tbl_Violator GetByID(int id)
{
return db.tbl_Violator.Find(id);
}
public void Insert(tbl_Violator Violator)
{
db.tbl_Violator.Add(Violator);
Save();
}
public void Delete(int id)
{
tbl_Violator Violator = db.tbl_Violator.Find(id);
db.tbl_Violator.Remove(Violator);
Save();
}
public void Update(tbl_Violator Violator)
{
db.Entry(Violator).State = EntityState.Modified;
Save();
}
public void Save()
{
db.SaveChanges();
}
}
2. Logic Layer
ViolatorBs
public class ViolatorBs
{
private ViolatorDB objDb;
public ViolatorBs()
{
objDb = new ViolatorDB();
}
public IEnumerable<tbl_Violator> GetALL()
{
return objDb.GetALL();
}
public tbl_Violator GetByID(int id)
{
return objDb.GetByID(id);
}
public void Insert(tbl_Violator Violator)
{
objDb.Insert(Violator);
}
public void Delete(int id)
{
objDb.Delete(id);
}
public void Update(tbl_Violator Vioaltor)
{
objDb.Update(Vioaltor);
}
}
And Finally using Logic Layer functions in presentation Layer.Here insertion is performed as:
public class CreateViolatorController : Controller
{
public TPCAEntities db = new TPCAEntities();
private ViolatorBs objBs;
public CreateViolatorController()
{
objBs = new ViolatorBs();
}
public ActionResult Index()
{
var voilator = new tbl_Violator();
voilator=db.tbl_Violator.Add(voilator);
ViewBag.id = voilator.VID;
return View();
}
[HttpPost]
public ActionResult Create(tbl_Violator Violator)
{
try
{
if (ModelState.IsValid)
{
objBs.Insert(Violator);
TempData["Msg"] = "Violator Created successfully";
return RedirectToAction("Index");
}
else
{
return View("Index");
}
}
catch (Exception ex)
{
TempData["Msg"] = "Failed..." + ex.Message + " " + ex.ToString();
return RedirectToAction("Index");
}
}
}
Now here is the main part how do i get perticuller inserted id in another controller named Dues while performing insertion ?
In sqlqery I would have used ##IDENTITY but in Entity Framework I'm not sure.
I'm new to mvc framework any suggestion or help is appreciated Thanks in Advance.
Once you save your db context the id is populated back to your entity by EF automatically.
for example.
using(var context = new DbContext())
{
var employee = new Employee(); //this has an id property
context.Employees.Add(employee);
context.SaveChanges();
var id = employee.id; // you will find the id here populated by EF
}
You dont need to add and save your table as you have done this already in your voilatorDB class just fetch the last id like following
var id = yourTableName.Id;
db.yourTableName.find(id);
Or you can simply write one line code to achive that using VoilatorBs class function
GetbyID(id);
I've been trying to implement David Hayden's Orchard CMS and ASP .NET Web API http://www.davidhayden.me/blog/orchard-cms-and-asp.net-web-api, but I'm running into problems, basically getting a page not found.
This is what I have:
Under my controllers
ContactViewModel.cs
namespace Sunkist.ContactManager.Controllers
{
public class ContactsController : ApiController
{
private readonly IContentManager _contentManager;
public ContactsController(IContentManager contentManager)
{
_contentManager = contentManager;
}
public IEnumerable<ContactViewModel> Get()
{
return _contentManager
.Query(VersionOptions.Published, "Contact")
.List()
.Select(c => new ContactViewModel(c));
}
public ContactViewModel Get(int id)
{
var contact = _contentManager.Get(id);
if (contact == null)
throw new HttpResponseException
(new HttpResponseMessage(HttpStatusCode.NotFound));
return new ContactViewModel(contact);
}
}
}
ViewModel folder
ViewModel.cs
namespace Sunkist.ContactManager.ViewModel
{
public class ContactViewModel
{
private Orchard.ContentManagement.ContentItem c;
public ContactViewModel(Orchard.ContentManagement.ContentItem c)
{
// TODO: Complete member initialization
this.c = c;
}
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
}
}
and migration
namespace Sunkist.ContactManager {
public class Migrations : DataMigrationImpl {
public int Create() {
// Creating table ContactRecord
SchemaBuilder.CreateTable("ContactRecord", table => table
.ContentPartRecord()
.Column("Name", DbType.String)
.Column("Address", DbType.String)
.Column("City", DbType.String)
);
return 1;
}
}
}
I'm new to both Orchard and .Net MVC, So I'm not sure what I'm doing wrong?
Double check the name of the module that contains the Web API controller.
Via VS GUI, I created a new web api controller class "TestController.cs" and could not find the correct endpoint url.
That is, until I looked at the Module.txt in the project I added the controller to. The project is "Orchard.Users", but the name in the Module.txt file is just "Users".
I was able to hit the endpoint at "http://example.com/api/users/test".
Noteworthy: I setup a route for this at ".../UsersApi", but the 'auto-magic' URL pattern still works. Code below. Also, I later added a new module to contain my api controller and it would not work until I enabled the module in the dashboard.
TestController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Orchard.Users.Controllers
{
public class TestController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}
HttpRoutes.cs
using System.Collections.Generic;
using Orchard.Mvc.Routes;
using Orchard.WebApi.Routes;
public class HttpRoutes : IHttpRouteProvider
{
public void GetRoutes(ICollection<RouteDescriptor> routes)
{
foreach (RouteDescriptor routeDescriptor in GetRoutes())
{
routes.Add(routeDescriptor);
}
}
public IEnumerable<RouteDescriptor> GetRoutes()
{
return new[] {
new HttpRouteDescriptor {
Name = "UsersApi",
Priority = -10,
RouteTemplate = "usersapi/{id}",
Defaults = new {
area = "Orchard.Users",
controller = "Test",
id = RouteParameter.Optional
},
}
};
}
}
i am very new to mvc web api
I have crated a web api Post method which takes an object type "Bag" and return a HTMLString the code is as shown bellow
public HtmlString PostBag(Bag bagofItem)
{
return Utility.PostBagDiscountedItem(bagofItem);
}
now from my web site i wanted to call the API method PostBag from the controller PostBag()
and i am do not know how to and appreciate if some one can show me how to do this
what i have got in my web application is as bellow.
public class HomeController : Controller
{
private Bag _bag = new Bag();
private string uri = "http://localhost:54460/";
public ActionResult PostBag()
{
// would some one show me how to POST the _bag to API Method PostBag()
return View();
}
public class Bag
{
private static List<Product> _bag { get; set; }
public List<Product> GetBag ()
{
if (_bag == null)
_bag = new List<Product>();
return _bag;
}
}
Try this:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:54460/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(_bag);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}
In my AdministratorController I have an action with custom attribute:
[AuthorizedOnly (Roles = "admin, superadmin")]
public ActionResult Index()
{...}
The attribute is:
class AuthorizedOnlyAttribute : AuthorizeAttribute
{
public AuthorizedOnlyAttribute()
{
View = "~/Views/Main/Index.cshtml";
Master = String.Empty;
}
public String View { get; set; }
public String Master { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
CheckIfUserIsAuthenticated(filterContext);
}
private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext)
{
if(filterContext.Result == null)
return;
if(filterContext.HttpContext.User.Identity.IsAuthenticated)
{
if(String.IsNullOrEmpty(View))
return;
var result = new ViewResult{ViewName = View, MasterName = Master};
filterContext.Result = result;
}
}
It correctly shows me the view that I need: ~/Views/Main/Index.cshtml
But in my browser URL is still from Administrator controller: .../Administrator/Index
How can I redirect to the View that I need, so that URL would also change?
Thanks a lot in advance!
Try this
string retUrl = filterContext.HttpContext.Request.RawUrl;
filterContext.Result =
new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary
{{ "controller", "Main" },
{ "action", "Home" },
{ "returnUrl", retUrl } });